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 魔术函数使用说明
Feb 21 PHP
一个简单的php加密解密函数(动态加密)
Jun 19 PHP
用PHP来计算某个目录大小的方法
Apr 01 PHP
简单的php新闻发布系统教程
May 09 PHP
ThinkPHP空模块和空操作详解
Jun 30 PHP
ThinkPHP模板输出display用法分析
Nov 26 PHP
php+mysql大量用户登录解决方案分析
Dec 29 PHP
学习php设计模式 php实现备忘录模式(Memento)
Dec 09 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
Aug 30 PHP
微信公众平台开发教程④ ThinkPHP框架下微信支付功能图文详解
Apr 10 PHP
Laravel 默认邮箱登录改成用户名登录的实现方法
Aug 12 PHP
如何用PHP实现多线程编程
May 26 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
在wamp集成环境下升级php版本(实现方法)
2013/07/01 PHP
PHP swfupload图片上传的实例代码
2013/09/30 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
CI框架整合widget(页面格局)的方法
2016/05/17 PHP
php post换行的方法
2020/02/03 PHP
精通Javascript系列之数据类型 字符串
2011/06/08 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
2013/08/05 Javascript
jQuery插件支持同一页面被多次调用
2016/02/14 Javascript
js计算系统当前日期是星期几的方法
2016/07/14 Javascript
功能强大的Bootstrap效果展示(二)
2016/08/03 Javascript
Vue.js系列之项目结构说明(2)
2017/01/03 Javascript
JS使用插件cryptojs进行加密解密数据实例
2017/05/11 Javascript
AngularJS创建一个上传照片的指令实例代码
2018/02/24 Javascript
深入理解react-router 路由的实现原理
2018/09/26 Javascript
Vuex的热更替如何实现
2020/06/05 Javascript
JavaScript原生数组函数实例汇总
2020/10/14 Javascript
[01:11:10]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG加赛
2014/05/26 DOTA
[46:48]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第三局
2016/02/25 DOTA
python分割文件的常用方法
2014/11/01 Python
Python中的闭包详细介绍和实例
2014/11/21 Python
Python获取DLL和EXE文件版本号的方法
2015/03/10 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
python实现词法分析器
2019/01/31 Python
python基础梳理(一)(推荐)
2019/04/06 Python
初次部署django+gunicorn+nginx的方法步骤
2019/09/11 Python
基于Python实现大文件分割和命名脚本过程解析
2019/09/29 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
Python Scrapy图片爬取原理及代码实例
2020/06/12 Python
一些常用的HTML5模式(pattern) 总结
2015/07/14 HTML / CSS
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
精通CAD能手自荐书
2014/01/31 职场文书
八荣八耻演讲稿
2014/09/15 职场文书
运动会铅球比赛加油稿
2014/09/26 职场文书
公司捐书倡议书
2015/04/27 职场文书
高效笔记技巧分享:学会这些让你不再困扰
2019/09/04 职场文书
mysql通过group by分组取最大时间对应数据的两种有效方法
2022/09/23 MySQL