>  기사  >  백엔드 개발  >  PHP 토큰(토큰) 디자인

PHP 토큰(토큰) 디자인

WBOY
WBOY원래의
2016-08-08 09:26:491450검색

재인쇄 링크: http://www.jb51.net/article/13756.htm

PHP 토큰 디자인 설계 목표: 데이터의 반복 제출 방지 외부 제출인지 소스를 확인하세요. 수행할 작업을 일치시킵니다(PHP 파일의 작업 추가, 삭제, 수정 등 동일한 페이지에 여러 논리가 구현된 경우). 여기에 언급된 토큰은 페이지가 표시될 때 FORM에 기록되는 숨겨진 토큰입니다. 양식 항목(유형=숨김) 토큰은 일반 텍스트일 수 없습니다. 일반 텍스트라면 너무 위험하므로 특정 암호화 방법을 사용해야 합니다. 내 알고리즘은 매우 바보같습니다.

반복 제출을 방지하는 방법은 무엇입니까?
SESSION에 배열을 저장합니다. 이 배열은 백그라운드 처리 중에 먼저 토큰이 있는지 확인합니다. 이 배열이 존재한다면 설명해주세요.
소스를 확인하는 방법은 무엇인가요?
선택사항, 이 토큰이 생성되면 다른 사람이 귀하의 HTML(토큰 복사본)을 복사하면 추가됩니다. 제출할 때 이론적으로 토큰에 포함된 session_id가 현재 session_id와 같지 않으면 이 제출이 외부 제출임을 확인할 수 있습니다.
실행할 액션을 어떻게 일치시킬 수 있나요?
토큰화할 때 토큰의 액션 이름을 토큰에 적어야 합니다. 이렇게 하면 처리 중에 액션을 디코딩하여 비교할 수 있습니다.

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;  
    }      
}  
?> 
메서드:
(1) granteToken 매개변수: formName, 이는 작업 이름, key는 암호화/해독 키입니다.
다음 형식으로 문자열을 반환합니다. formName:session_id)
(2) isToken 매개변수: token은 granteToken, formName, action 이름으로 생성된 결과로 fromCheck가 출처를 확인하는지 여부를 나타내며, true인 경우 토큰에 session_id가 있는지 확인하는 것도 필요합니다. 현재 session_id와 동일합니다.
(3) dropToken, 작업을 성공적으로 실행한 후 이 함수를 호출하고 $_POST에서

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;  
    }  
}  
?> 

세션에 토큰을 기록합니다.

일치하는 작업인지 판단하려면 isToken에서 formName을 변경하고 실행하면 됩니다.

위 내용은 PHP Token의 디자인을 다양한 측면에서 소개하고 있으며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.