Home  >  Article  >  Backend Development  >  PHP Token (token) design

PHP Token (token) design

WBOY
WBOYOriginal
2016-08-08 09:26:491453browse

Reprint link: http://www.jb51.net/article/13756.htm

PHP Token design design goal: avoid repeated submission of data. Check the source to see if it is an external submission matching the action to be performed ( If there are multiple logics implemented on the same page, such as adding, deleting, and modifying operations in a PHP file) The token mentioned here is a hidden form item (type=hidden) written to the FORM when the page is displayed. ). The token cannot be plaintext. If it is plaintext, it would be too dangerous, so a certain encryption method must be used. The ciphertext must be reversible. My algorithm is very idiotic, so I used a ready-made method on the Internet.

How to avoid repeated submissions?
An array must be stored in SESSION. This array stores successfully submitted tokens. During background processing, first determine whether the token is in this array. If it exists, it means that it is a repeated submission.
How to check the origin?
Yes option, when this token is generated, the current session_id is added. If someone else copies your html (token copy), when submitting, theoretically the session_id contained in the token is not equal to the current session_id, and this submission can be judged It is an external submission.
How to match the action to be executed?
When tokenizing, the action name of this token must be written into the token, so that during processing, the action can be decoded and compared.

GEncrypt.inc. php:

<?php  
class GEncrypt extends GSuperclass {  
    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(rand(0,32000));  
        $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 base64_encode(self::keyED($tmp,$key));  
    }  

    public static function decrypt($txt,$key){  
        $txt = self::keyED( base64_decode($txt),$key);     
        $tmp = "";  
        for ($i=0;$i<strlen($txt);$i++){     
            $md5 = substr($txt,$i,1);     
            $i++;     
            $tmp.= (substr($txt,$i,1) ^ $md5);     
        }  
        return $tmp;  
    }      
}  
?> 
method:
(1) granteToken Parameter: formName, which is the action name, key is the encryption/decryption key.
Returns a string in the form: encryption (formName: session_id)
(2) isToken Parameter: token That is The result generated by granteToken, formName, action name, and whether fromCheck check the origin, if true, also determine whether the session_id in the token is consistent with the current session_id.
(3) dropToken, when an action is successfully executed, call this function and record the token into the session.

GToken.inc.php

<?php  
/**  
* 原理:请求分配token的时候,想办法分配一个唯一的token, base64( time + rand + action)  
* 如果提交,将这个token记录,说明这个token以经使用,可以跟据它来避免重复提交。  
*  
*/  
class GToken {  

    /**  
     * 得到当前所有的token  
     *  
     * @return array  
     */  
    public static function getTokens(){  
        $tokens = $_SESSION[GConfig::SESSION_KEY_TOKEN ];  
        if (empty($tokens) && !is_array($tokens)) {  
            $tokens = array();  
        }  
        return $tokens;  
    }  

    /**  
     * 产生一个新的Token  
     *  
     * @param string $formName  
     * @param 加密密钥 $key  
     * @return string  
     */  

    public static function granteToken($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){  
        $tokens = self::getTokens();  

        if (in_array($token,$tokens)) //如果存在,说明是以使用过的token  
            return false;  

        $source = split(":", GEncrypt::decrypt($token,$key));  

        if($fromCheck)  
            return $source[1] == session_id() && $source[0] == $formName;  
        else  
            return $source[0] == $formName;  
    }  
}  
?> 

Retrieve the token from $_POST and use isToken to judge.

If you want to judge Whether it is a matching action to be executed, you can change the formName in isToken and run it. It is fine, but there is no match. This proves that this is successful.

The above introduces the design of PHP Token, including various aspects. I hope it will be helpful to friends who are interested in PHP tutorials.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn