PHP实例:避免重复提交和检查数据来路

网络整理 - 08-25
 PHP Token(令牌)设计

  设计目标:

  避免重复提交数据.

  检查来路,是否是外部提交

  匹配要执行的动作(如果有多个逻辑在同一个页面实现,比如新增,删除,修改放到一个PHP文件里操作)

  这里所说的token是在页面显示的时候,写到FORM的一个隐藏表单项(type=hidden).

  token不可明文,如果是明文,那就太危险了,所以要采用一定的加密方式.密文要可逆.俺算法很白痴,所以采用了网上一个现成的方法.

  如何达到目的:

  怎样避免重复提交?

  在SESSION里要存一个数组,这个数组存放以经成功提交的token.在后台处理时,先判断这个token是否在这个数组里,如果存在,说明是重复提交.

  如何检查来路?

  可选项,这个token在生成的时候,加入了当前的session_id.如果别人copy你的html(token一迸copy),在提交时,理论上token里包含的session_id不等于当前session_id,就可以判断这次提交是外部提交.

  如何匹配要执行的动作?

  在token的时候,要把这个token的动作名称写进这个token里,这样,在处理的时候,把这个动作解出来进行比较就行了.

  我以前写的GToken不能达到上面所说的第二条,今天修改了一下,把功能2加上了.个人感觉还行.

  请大家看代码,感觉哪里有不合理的地方,还请赐教!谢谢.

  加密我是找的网上的一个方法,稍作了一下修改.

  GEncrypt.inc.PHP:


 <?php
  class GEncrypt extends GSuperclass {
  protected static function keyED($txt,$encrypt_key){
  $encrypt_key = md5($encrypt_key);
  $ctr=0;
  $tmp = "";
  for ($i=0;$i 
  if ($ctr==strlen($encrypt_key)) $ctr=0;
  $tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
  $ctr++;
  }
  return $tmp;
  }
  public static function encrypt($txt,$key){
  //$encrypt_key = md5(rand(0,32000));
  $encrypt_key = md5(((float) date("YmdHis") + rand(10000000000000000,99999999999999999)).rand(100000,999999));
  $ctr=0;
  $tmp = "";
  for ($i=0;$i 
  if ($ctr==strlen($encrypt_key)) $ctr=0;
  $tmp.= substr($encrypt_key,$ctr,1) . (substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));
  $ctr++;
  }
  return base64_encode(self::keyED($tmp,$key));
  }
  public static function decrypt($txt,$key){
  $txt = self::keyED( base64_decode($txt),$key);
  $tmp = "";
  for ($i=0;$i 
  $md5 = substr($txt,$i,1);
  $i++;
  $tmp.= (substr($txt,$i,1) ^ $md5);
  }
  return $tmp;
  }
  }
  ?>

  GToken.inc.php

  方法:

  a,granteToken 参数:formName,即动作名称,key是加密/解密 密钥.

  返回一个字符串,形式是: 加密(formName:session_id)

  b,isToken 参数:token 即granteToken产生的结果,formName,动作名称,fromCheck是否检查来路,如果为真,还要判断token里的session_id是否和当前的session_id一至.

  c,dropToken,当成功执行一个动作后,调用这个函数,把这个token记入session里,