PHP令牌 Token改进版


Posted in PHP onJuly 18, 2008

正是由于使用了 base64 ,所以在把这个令牌通过 GET方法发送的时候,出现了问题。
比如:http://test/test.php?a=1+2
你用 $_GET["a"] 取得是:1 2 ,即那个加号没有了。一开始我用 urlencode 对其进行转换,但是总有那么一两的结果是意料外的。

后来想想 base64 的字符就限定于: [A-Za-z0-9\+\/=] 这么多,加号出问题,我就把加号换成不出问题的符号,下划线是最好的选择。下面是修改后的代码:

GEncrypt.inc.php

<?php  
class GEncrypt {  
 protected static function keyED($txt, $encrypt_key) {  
  $encrypt_key = md5 ( $encrypt_key );  
  $ctr = 0;  
  $tmp = "";  
  for($i = 0; $i < strlen ( $txt ); $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 ( (( float ) date ( "YmdHis" ) + rand ( 10000000000000000, 99999999999999999 )) . rand ( 100000, 999999 ) );  
  $ctr = 0;  
  $tmp = "";  
  for($i = 0; $i < strlen ( $txt ); $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 ( preg_replace("/\\+/s","_", base64_encode ( self::keyED ( $tmp, $key ) ) ));  
 }  
 //base64 [A-Za-z0-9\+\/=]  
 public static function decrypt($txt, $key) {  
  if($txt == ""){ return false;}   
  //echo preg_replace("/_/s","+",$txt);  
  $txt = self::keyED (base64_decode ( preg_replace("/_/s","+", $txt) ), $key );  
  $tmp = "";  
  for($i = 0; $i < strlen ( $txt ); $i ++) {  
   $md5 = substr ( $txt, $i, 1 );  
   $i ++;  
   $tmp .= (substr ( $txt, $i, 1 ) ^ $md5);  
  }  
  return $tmp;  
 }  
}  
?> 

GToken.inc.php
<?php  
/**  
 * 原理:请求分配token的时候,想办法分配一个唯一的token, base64( time + rand + action)  
 * 如果提交,将这个token记录,说明这个token以经使用,可以跟据它来避免重复提交。  
 *  
 */  
class GToken {   /**  
  * 得到当前所有的token  
  *  
  * @return array  
  */  
 public static function getTokens(){  
  $tokens = $_SESSION[GConfig::SSN_KEY_TOKEN ];  
  if (empty($tokens) && !is_array($tokens)) {  
   $tokens = array();  
  }  
  return $tokens;  
 }  
 /**  
  * 产生一个新的Token  
  *  
  * @param string $formName  
  * @param 加密密钥 $key  
  * @return string  
  */  
 public static function newToken($formName,$key = GConfig::ENCRYPT_KEY ){  
  $token = GEncrypt::encrypt($formName.session_id(),$key);  
  return $token;  
 }  
 /**  
  * 删除token,实际是向session 的一个数组里加入一个元素,说明这个token以经使用过,以避免数据重复提交。  
  *  
  * @param string $token  
  */  
 public static function dropToken($token){  
  $tokens = self::getTokens();  
  $tokens[] = $token;  
  GSession::set(GConfig::SESSION_KEY_TOKEN ,$tokens);  
 }  
 /**  
  * 检查是否为指定的Token  
  *  
  * @param string $token 要检查的token值  
  * @param string $formName   
  * @param boolean $fromCheck 是否检查来路,如果为true,会判断token中附加的session_id是否和当前session_id一至.  
  * @param string $key 加密密钥  
  * @return boolean  
  */  
 public static function isToken($token,$formName,$fromCheck = false,$key = GConfig::ENCRYPT_KEY){  
  if(empty($token)) return false;  
  $tokens = self::getTokens();  
  if (in_array($token,$tokens)) //如果存在,说明是以使用过的token  
   return false;  
  $source = GEncrypt::decrypt($token,$key);  
  if($fromCheck)  
   return $source == $formName.session_id();  
  else{  
   return strpos($source,$formName) === 0;  
  }  
 }  
 public static function getTokenKey($token,$key = GConfig::ENCRYPT_KEY){  
  if($token == null || trim($token) == "") return false;  
  $source = GEncrypt::decrypt($token,$key);  
  return $source != "" ? str_replace(session_id(),"",$source) : false;  
 }  
 public function newTokenForSmarty($params){  
  $form = null;  
  extract($params);  
  return self::newToken($form);  
 }  
}  
?> 
PHP 相关文章推荐
PHP的一个完整SMTP类(解决邮件服务器需要验证时的问题)
Oct 09 PHP
Get或Post提交值的非法数据处理
Oct 09 PHP
自动把纯文本转换成Web页面的php代码
Aug 27 PHP
PHP 程序员应该使用的10个组件
Oct 31 PHP
解析wamp5下虚拟机配置文档
Jun 27 PHP
php计算几分钟前、几小时前、几天前的几个函数、类分享
Apr 09 PHP
PHP防范SQL注入的具体方法详解(测试通过)
May 09 PHP
Laravel框架学习笔记(二)项目实战之模型(Models)
Oct 15 PHP
PHP时间和日期函数详解
May 08 PHP
PHP中的类型提示(type hinting)功能介绍
Jul 01 PHP
php使用变量动态创建类的对象用法示例
Feb 06 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
Dec 21 PHP
php下intval()和(int)转换使用与区别
Jul 18 #PHP
PHP入门学习的几个不错的实例代码
Jul 13 #PHP
php header()函数使用说明
Jul 10 #PHP
php下实现一个阿拉伯数字转中文数字的函数
Jul 10 #PHP
兼容PHP5的PHP目录管理函数库
Jul 10 #PHP
php 防止单引号,双引号在接受页面转义
Jul 10 #PHP
功能齐全的PHP发送邮件类代码附详细说明
Jul 10 #PHP
You might like
详解WordPress开发中的get_post与get_posts函数使用
2016/01/04 PHP
PHP简单实现合并2个数字键数组值的方法
2017/05/30 PHP
PHP实现的无限分类类库定义与用法示例【基于thinkPHP】
2018/08/06 PHP
Laravel框架中队列和工作(Queues、Jobs)操作实例详解
2020/04/06 PHP
js函数使用技巧之 setTimeout(function(){},0)
2009/02/09 Javascript
JQuery动态创建DOM、表单元素的实现代码
2011/08/09 Javascript
页面只能打开一次Cooike如何实现
2012/12/04 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
简介JavaScript中substring()方法的使用
2015/06/06 Javascript
跟我学习javascript的call(),apply(),bind()与回调
2015/11/16 Javascript
超实用的javascript时间处理总结
2016/08/16 Javascript
微信分享调用jssdk实例
2017/06/08 Javascript
取消Bootstrap的dropdown-menu点击默认关闭事件方法
2018/08/10 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
2018/09/19 Javascript
vue-cli中vue本地实现跨域调试接口
2019/01/16 Javascript
jQuery实现input输入框获取焦点与失去焦点时提示的消失与显示功能示例
2019/05/27 jQuery
jquery.pager.js分页实现详解
2019/07/29 jQuery
[36:33]Ti4 循环赛第四日 附加赛NEWBEE vs Mouz
2014/07/13 DOTA
关于你不想知道的所有Python3 unicode特性
2014/11/28 Python
Python实现的凯撒密码算法示例
2018/04/12 Python
jupyter notebook tensorflow打印device信息实例
2020/04/20 Python
python爬虫容易学吗
2020/06/02 Python
django和flask哪个值得研究学习
2020/07/31 Python
美国销售第一的智能手机和平板电脑保护壳:OtterBox
2017/12/21 全球购物
英国Office鞋店德国网站:在线购买鞋子、靴子和运动鞋
2018/12/19 全球购物
Chain Reaction Cycles俄罗斯:世界上最大的在线自行车商店
2019/08/27 全球购物
No7 Beauty美国官网:英国国民护肤品牌
2019/10/31 全球购物
27个经典Linux面试题及答案,你知道几个?
2014/03/11 面试题
毕业生个人求职的自我评价
2013/10/28 职场文书
网上开店必备创业计划书
2014/01/26 职场文书
幼儿园教育教学反思
2014/01/31 职场文书
五四青年节演讲稿
2014/05/26 职场文书
品质标语大全
2014/06/21 职场文书
优秀会计求职信
2014/07/04 职场文书
电信营业员岗位职责
2015/04/14 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书