天天看點

zhphp framework (二十八) token 加密與解密

<?php
/**
 * Created by PhpStorm.
 * User: zhanghua
 * Date: 14-2-5
 * Time: 23:28
 * QQ: 746502560qq.com
 */
/**
* 原理:請求配置設定token的時候,想辦法配置設定一個唯一的token, base64( time + rand + action)
* 如果送出,将這個token記錄,說明這個token以經使用,可以跟據它來避免重複送出。
*/
final class token {
    /**
     * 得到目前所有的token
     *
     * @return array
     */
    public static function getTokens(){
        $key=config::readConfig('sesssion', 'key_token');
        $key=(!empty($key))?$key:null;
        $tokens=isset($_SESSION["{$key}"])?$_SESSION["{$key}"]:array();#解決session中出現undefined
        if (empty($tokens) && !is_array($tokens)){
            $tokens = array();
        }
		unset($key);
        return $tokens;
    }
    /**
     * 産生一個新的Token
     * @param string $formName
     * @param 加密密鑰 $key
     * @return string
     */
    public static function granteToken($formName,$key =''){
        $key=empty($key)?config::readConfig('sesssion', 'key_token'):$key;
        $token = self::encrypt($formName.':'.session_id().':'.time(),$key);
		unset($key,$formName);
        return $token;
    }
    /**
     *  加密
     * @param type $str
     * @param type $key
     * @return type
     */
    public static function encrypt($str, $key=''){
        $key=  empty($key)?config::readConfig('sesssion', 'key_token'):$key;
        $coded = '';
        $keylength = strlen($key);
        $leng=strlen($str);
        for ($i = 0, $count = $leng; $i < $count; $i += $keylength) {
            $coded .= substr($str, $i, $keylength) ^ $key;
        }
		$newCode=str_replace('=', '', base64_encode($coded));
		unset($str,$key,$coded,$keylength,$leng);
		return $newCode;
    }
    /**
     * 解密
     * @param type $str
     * @param type $key
     * @return type
     */
    public static function decrypt($str, $key = ''){
        $key=  empty($key)?config::readConfig('sesssion', 'key_token'):$key;
        $coded = '';
        $keylength = strlen($key);
        $str = base64_decode($str);
        for ($i = 0, $count = strlen($str); $i < $count; $i += $keylength){
            $coded .= substr($str, $i, $keylength) ^ $key;
        }
		unset($str,$key,$keylength);
        return $coded;
    }
    
    /**
     * 删除token,實際是向session 的一個數組裡加入一個元素,說明這個token以經使用過,以避免資料重複送出。
     *
     * @param string $token
     */
    public static function dropToken($token){
        $tokens = self::getTokens();
        $tokens[] = $token;
        $_SESSION[config::readConfig('sesssion', 'key_token')]=$tokens;
		unset($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 =''){
         $tokens = self::getTokens();
         if (in_array($token,$tokens)){ //如果存在,說明是以使用過的token
		    unset($tokens);
            return false;
         }
		 $key=  empty($key)?config::readConfig('sesssion', 'key_token'):$key;
         $source = explode(':',self::decrypt($token,$key));
		 unset($token,$key);
         if($fromCheck){
            if($source[1] == session_id() && $source[0] == $formName){
			 unset($source,$formName);
             return true;
            }else{
			 unset($source,$formName);
             return false;
            }
         }else{
             if($source[0] == $formName){
			 unset($source,$formName);
             return true;
             }else{
                unset($source,$formName);
                return false;
             }
        }
     }
}