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面试题附答案
Jan 07 PHP
PHP实现多条件查询实例代码
Jul 17 PHP
php设计模式 Strategy(策略模式)
Jun 26 PHP
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
Aug 18 PHP
PHP连接SQLSERVER 注意事项(附dll文件下载)
Jun 28 PHP
php中计算未知长度的字符串哪个字符出现的次数最多的代码
Aug 14 PHP
php标签云的实现代码
Oct 10 PHP
ThinkPHP3.1基础知识快速入门
Jun 19 PHP
ThinkPHP的模版中调用session数据的方法
Jul 01 PHP
浅谈php的优缺点
Jul 14 PHP
php实现带读写分离功能的MySQL类完整实例
Jul 28 PHP
TP5框架实现上传多张图片的方法分析
Mar 29 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
PHP中的数组处理函数实例总结
2016/01/09 PHP
PHP序列化/对象注入漏洞分析
2016/04/18 PHP
php单例模式的简单实现方法
2016/06/10 PHP
用JavaScript和注册表脚本实现右键收藏Web页选中文本
2007/01/28 Javascript
JS实现点击链接取消跳转效果的方法
2014/01/24 Javascript
jQuery照片伸缩效果不影响其他元素的布局
2014/05/09 Javascript
jQuery如何获取同一个类标签的所有值(默认无法获取)
2014/09/25 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
详解Vue-Cli 异步加载数据的一些注意点
2017/08/12 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
2018/05/17 Javascript
js使用swiper实现层叠轮播效果实例代码
2018/12/12 Javascript
在JavaScript中如何访问暂未存在的嵌套对象
2019/06/18 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
js实现上传图片并显示图片名称
2019/12/18 Javascript
Python异常处理总结
2014/08/15 Python
在Python中使用matplotlib模块绘制数据图的示例
2015/05/04 Python
Using Django with GAE Python 后台抓取多个网站的页面全文
2016/02/17 Python
基于Python中capitalize()与title()的区别详解
2017/12/09 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
Python读取txt内容写入xls格式excel中的方法
2018/10/11 Python
CSS3制作3D立方体loading特效
2020/11/09 HTML / CSS
GafasWorld哥伦比亚:网上购买眼镜
2017/11/28 全球购物
马来西亚银饰品牌:JEOEL
2017/12/15 全球购物
Gibson London官网:以地道的英国男装而著称
2019/12/06 全球购物
美国在线艺术商店:HandmadePiece
2020/11/06 全球购物
体育专业学生自我评价范文
2014/01/17 职场文书
幼儿园教师个人反思
2014/01/30 职场文书
简历里的自我评价范文
2014/02/24 职场文书
违反交通法规检讨书
2014/09/10 职场文书
校本培训个人总结
2015/02/28 职场文书
信访工作个人总结
2015/03/03 职场文书
信息技术国培研修日志
2015/11/13 职场文书
Linux中Nginx的防盗链和优化的实现代码
2021/06/20 Servers
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript
动画《朋友游戏》公开佐藤友生绘制的开播纪念绘
2022/04/06 日漫