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调用Oracle存储过程
Oct 09 PHP
PHP 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
Dec 07 PHP
PHP获取当前url的具体方法全面解析
Nov 26 PHP
PHP数组遍历知识汇总(包含遍历方法、数组指针操作函数、数组遍历测速)
Jul 05 PHP
浅谈php和.net的区别
Sep 28 PHP
CentOS安装php v8js教程
Feb 26 PHP
PHP中如何防止外部恶意提交调用ajax接口
Apr 11 PHP
一个实用的php验证码类
Jul 06 PHP
PHP简单实现记录网站访问量功能示例
Jun 06 PHP
PHP基于rabbitmq操作类的生产者和消费者功能示例
Jun 16 PHP
PHP连接SQL Server的方法分析【基于thinkPHP5.1框架】
May 06 PHP
PHP与SQL语句写一句话木马总结
Oct 11 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 SQL之where语句生成器
2009/03/24 PHP
php 生成随机验证码图片代码
2010/02/08 PHP
PHP 最大运行时间 max_execution_time修改方法
2010/03/08 PHP
PHP中去除换行解决办法小结(PHP_EOL)
2011/11/27 PHP
ThinkPHP权限认证Auth实例详解
2014/07/22 PHP
php cookie中点号(句号)自动转为下划线问题
2014/10/21 PHP
PHP魔术方法以及关于独立实例与相连实例的全面讲解
2016/10/18 PHP
PHP设计模式之状态模式定义与用法详解
2018/04/02 PHP
escape、encodeURI、encodeURIComponent等方法的区别比较
2006/12/27 Javascript
js文字滚动停顿效果代码
2008/06/28 Javascript
利用ajaxfileupload插件实现文件上传无刷新的具体方法
2013/06/08 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
2013/08/02 Javascript
让jQuery与其他JavaScript库并存避免冲突的方法
2013/12/23 Javascript
JS遍历Json字符串中键值对先转成JSON对象再遍历
2014/08/15 Javascript
修复bash漏洞的shell脚本分享
2014/12/31 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
2016/01/15 Javascript
canvas 绘制圆形时钟
2017/02/22 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
2017/03/31 Javascript
基于jquery ajax的多文件上传进度条过程解析
2019/09/11 jQuery
element-ui table组件如何使用render属性的实现
2019/11/04 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
python 函数传参之传值还是传引用的分析
2017/09/07 Python
python中pika模块问题的深入探究
2018/10/13 Python
python 的 scapy库,实现网卡收发包的例子
2019/07/23 Python
Python logging模块异步线程写日志实现过程解析
2020/06/30 Python
django使用channels实现通信的示例
2020/10/19 Python
基于python爬取梨视频实现过程解析
2020/11/09 Python
致百米运动员广播稿
2014/01/29 职场文书
艺术设计专业求职自荐信
2014/05/19 职场文书
食品工程专业求职信
2014/06/15 职场文书
迟到检讨书
2015/01/26 职场文书
2015年学生会工作总结范文
2015/03/31 职场文书
节约用电倡议书
2015/04/28 职场文书
中学团支部工作总结
2015/08/13 职场文书
小学生一年级(书信作文)
2019/08/13 职场文书
基于Python和openCV实现图像的全景拼接详细步骤
2021/10/05 Python