美文网首页
token身份验证机制

token身份验证机制

作者: X1_blog | 来源:发表于2020-05-07 18:54 被阅读0次

    作用: 替代 session 的身份验证方案

    运行过程:

    image.png

    token相对cookie, session 的优点 :

    1. 不用将数据暴露给客户端(cookie)
    
    2. 不需要存储大量信息, 而是存一个字符串, 减轻存储压力 ; 存放位置从服务器内存转到数据库, 避免因用户量增大时登录状态异常
    3. 对于分布式服务器架构支持好, 避免了访问其他服务器登录无效(session)
    

    流行的跨域认证解决方案: JWT

    JWT相对传统token的优点:

    1. 不需要查询数据库, 解密判定用户状态速度更快
    2. 支持签名加密, 防止数据(head/payload)篡改

    构成

    header + payload + Signature

    如何解决超有效期?如何判断离线?

    JWT算法:

    $code1= base64UrlEncode( header ) . "." . base64UrlEncode( payload )

    signature = base64UrlEncode(alg_type(code1))

    jwt =code1 . "." . $signature

    base64UrlEncode算法:

    字符串进行一次base64Encode, 将所得新字符串的=清除, "+" 替换为"-", "/" 替换为 "_"

    Base64UrlDecode算法:

    ...

    JWT运行过程:

    image.png

    JWT token demo https://www.jb51.net/article/146790.htm

    /*jwt加密测试*/
    date_default_timezone_set('Asia/Shanghai');
    class jwt{
        public $jwtcode;
        private $alg_array = [
            "HS256" => "sha256"
        ], 
        $key = "secret";
    
        function __construct($header,$payload){
            $this->header = $header;
            $this->payload = $payload;
        }
        
        function getJwtcode($alg="HS256"){
             $str = $this->base64UrlEncode($this->header) . "." . $this->base64UrlEncode($this->payload) ;
             $this->jwtcode = $str.".". $this->get_signature($str,$alg);
             return $this->jwtcode  ;
        }
    
        function base64UrlEncode($mixed)
        {
            if(gettype($mixed)!=="string")$mixed = json_encode($mixed,JSON_UNESCAPED_UNICODE);
            $str = base64_encode($mixed) ;
            $str = str_replace("=","",$str);
            $str = str_replace("+","-",$str);
            return $str = str_replace("/","_",$str);
        }
    
    
         private function base64UrlDecode(string $input)
          {
            $remainder = strlen($input) % 4;
            if ($remainder) {
              $addlen = 4 - $remainder;
              $input .= str_repeat('=', $addlen);
            }
            return base64_decode(strtr($input, '-_', '+/'));
          }
         
    
        function test(){
            $code ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o";   // 覆盖官网生成的jwt
            echo ( $this->jwtcode === $code )?  "true" :  "false" ;
        }
    
        function get_signature($str,$alg){
            return $this->base64UrlEncode(hash_hmac($this->alg_array[$alg],$str, $this->key,true));
        }
    
        
    
        function validateJwtcode($str){
            $array = explode(".", $str);
            $signature = $array[2];
            $header = json_decode($this->base64UrlDecode($array[0]),JSON_UNESCAPED_UNICODE);
            $payload = json_decode($this->base64UrlDecode($array[1]),JSON_UNESCAPED_UNICODE);
    
            $this->header = $header;
            $this->payload = $payload;
            $alg = $header['alg'];
    
            $new_signature = $this->get_signature($array[0].'.'.$array[1], $alg);
    
            if($new_signature!==$signature){
                echo "数据篡改";
                return;
            }
    
            echo ($payload['exp'] - time() <=0) ? "超时过期" : "校验成功" ;
    
        }
    }
    $header = [
      "alg"=> "HS256",
      "typ"=> "JWT"
    ];
    $payload = [
      "sub"=> "1234567890",
      "name" => "John Doe",
      "exp" => strtotime('2020-04-01 01:29:00') ,
    ];
    $jwt = new jwt($header,$payload) ;
    $jwtCode = $jwt->getJwtcode();      // 获取jwt
    echo $jwtCode ."\n" ;
    $jwt->validateJwtcode($jwtCode);    // 验证jwt可用, 验证身份时效
    

    MD5 token demo

    /*简单实现多种加密的token
    $payload : exp(过期时间) + alg(加密算法) + 其他信息
    $token = base64($payload) + "." + alg(base64($payload),$tokenKey)
    */
    date_default_timezone_set('Asia/Shanghai');
    class myToken{
        public $tokenCode = "";
        private $_alg_list = [
            "A" => "md5",
            "B" => "sha256",
        ];
        private $_tokenKey = "key" ;
        function base64encodeArray($array){
            $str = json_encode($array,JSON_UNESCAPED_UNICODE);
            return base64_encode($str);
        }
    
        function base64decodeArray($array){
    
        }
    
        function validateToken($str){
            $str_array = explode(".",$str);
            $payloadStr = $str_array[0];
            $signature = $str_array[1];
            $payloadStr = base64_decode($payloadStr);
            $payload = json_decode($payloadStr,JSON_UNESCAPED_UNICODE);
            $alg = $payload['alg'];
    
            $newSignature = $this->signatureEncode($str_array[0],$alg);
            if($signature !== $newSignature) echo "数据篡改" ;
            $exp = $payload['exp'];
            echo ($exp - strtotime("now") <=0 )? "超过有效期" : "token有效" ;
            
        }
    
        private function signatureEncode($str,$alg){
            $alg = $this->_alg_list[$alg];
            if($alg==="md5"){
                return md5($str.$this->_tokenKey);
            }
            if($alg==="sha256"){
                return hash_hmac("sha256",$str,$this->_tokenKey,$this->_tokenKey);
            }
    
        }
    
        public function get_tokenCode($payload){
            $alg = $payload['alg'];
            $base64Payload = $this->base64encodeArray($payload);
            $signature = $this->signatureEncode($base64Payload,$alg);
            return  $base64Payload . '.' . $signature ;
        }
        
    }
    
    $payload = [
        "alg" => "A" ,
        "sub"=> "1234567890",
        "name" => "John Doe",
        "exp" => strtotime('2020-04-02 15:34:00') ,
    ];
    $token = new myToken();
    $tokenCode = $token->get_tokenCode($payload);
    $token->validateToken($tokenCode);
    

    相关文章

      网友评论

          本文标题:token身份验证机制

          本文链接:https://www.haomeiwen.com/subject/thxtghtx.html