有时候,你需要对加密的字符串加上时间限制。 比如一个小时后失效。类似这种需求, 利用开源算法authcode会很好用, 可是它会出现一些特殊字符串,并且出现解密失效的情况。
别人的算法看起来费劲,改起来更费劲, 不如自己写个简单的,直接上代码
/**
* 算法思路。
* 0、遍历将$a的每位字符都先获取ascii码,再加上2,再返回该值对应的字符
* 1、获取$a的长度 $b,再将$b转化为16进制。
* 2、再求$b的长度 $c,再将$c转化为16进制。$c的长度将为1位。因为$a的长度不允许达到16的15次幕
* 3、将用户传入的时间戳 加上当前时间戳得到$time.
* 4、再将用户传入的密钥进行一定规则编码得到$d ,
* 5、定义不重复的9位字符串$m, 再对$time进行从后到前循环循环。
* 每次循环拿到 $m[$time[$i-1]] 再将其拼装起来得到 $times。 因为$time每位的值肯定不会超过9. 所以不会有超出长度的问题
* 6、生成一个 位数(1-10)随机 的 随机字符串 $f
* 7、$res = $c.$times.$b.$a.$f;
* 8、再将$res 按照规则来打散及重新拼装。如字符串 12345678 ,最后一位,第一位。倒数第二位。第二位....最终得到81726354.
*
* 带时间戳算法加密(不限长度)
* @param $a 待加密字符串
* @param int $time 加密时长
* @param $key 密钥
*/
public static function auth_encode($a,$time=0,$key){
$keya = md5 ( substr ( $key, 0, 16 ) );
$keyb = md5 ( substr ( $key, 16, 16 ) );
$key = md5($keya.$keyb.substr($key,0,10));
for($i=0,$n=strlen($a);$i<$n;$i++){
$a[$i] = chr(ord($a[$i])+2);
}
$time = $time ? ($time + time()): time();
$time = (string) sprintf("%012d",$time);
$strlen = dechex(strlen($a)); //代表字符串的长度
$strlen1 = dechex(strlen($strlen)); //保证字符串长度的长度是一位。 因为此数最大15, 而字符串的长度可达到16的15次幕。所以绝对够用。
$times = "";
$str = "UsHlpba8nD";
for($i=12;$i>0;$i--){
$times .= $str[$time[$i-1]];
}
$res = $strlen1.$times.$strlen.$a.$key.self::rands(rand(1,10));
$return = "";
for($i=0,$n=strlen($res);$i<ceil($n/2);$i++){
if($n-$i-1 == $i ){ //如果字符长度为
$return .= $res[$i];
}else{
$return .= $res[$n-$i-1].$res[$i];
}
}
return urlencode($return);
}
/**
* 对于上面的方法去进行解密
* 自定义带时间戳算法解密
* @param $a
* @param $key
*/
public static function auth_decode($a,$key){
$a = urldecode($a);
$keya = md5 ( substr ( $key, 0, 16 ) );
$keyb = md5 ( substr ( $key, 16, 16 ) );
$key = md5($keya.$keyb.substr($key,0,10));
$return = "";
for($i=1,$n=strlen($a);$i<=floor($n/2);$i++){
$return .= $a[2*$i-1];
}
for($i=ceil(strlen($a)/2);$i>0;$i--){
$return .= $a[2*$i-2];
}
$strlen1 = hexdec(substr($return,0,1));
$times = substr($return,1,12) ;
$strlen = hexdec(substr($return,13,$strlen1)); //真正有用的字符串长度
$code = substr($return,(13+$strlen1),$strlen);
$time = "";
for($i=strlen($times);$i>0;$i--){
$time .= strpos("UsHlpba8nD",$times[$i-1]);
}
$time = (int) $time;
if($time < time()){
return 0;//代表过期
}
if(strpos(substr($return,(13+$strlen+$strlen1)),$key) ===0 ){
for($i=0,$n=strlen($code);$i<$n;$i++){
$code[$i] = chr(ord($code[$i])-2);
}
return $code;
}else{
return false; //密钥不等
}
}
/**
* 随机生成 $n位字符
* @param $n
* @return string
*/
private static function rands($n){
$randstirng ="abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRST";
$returns = "";
for($i=0;$i<$n;$i++){
$rand = rand(0,strlen($randstirng)-1);
$returns .= $randstirng[$rand];
}
return $returns;
}
当然此算法并不够完美,还是会出现特殊字符,但保证能够完美解密