JWT理解

JWT由三个部分组成,基于token的身份验证可以替代传统的cookie+session身份验证方法。三个部分分别如下:

header.payload.signature

header部分组成

{
    "typ":"JWT",
    "alg":"HS256"
}

 

这就是一个json串,两个字段都是必须的,alg字段指定了生成signature的算法,默认值为 HS256,可以自己指定其他的加密算法,如RSA.经过base64encode就可以得到 header.

payload 部分组成

playload 基本组成部分,还可以自己添加一些字段:

$payload=[
   'iss' => $issuer, //签发人
   'iat' => $_SERVER['REQUEST_TIME'], //签发时间
   'exp' => $_SERVER['REQUEST_TIME'] + 7200 //过期时间
   'uid'=>1111
];

payload 也是一个json数据,是表明用户身份的数据,可以自己自定义字段,很灵活。经过json_encodebase64_encode就可得到payload

signature组成部分

将 header和 payload使用header中指定的加密算法加密,secret是自己定义的秘钥。用于验证数据签名。

官网实例:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

 

实例:

<?php
class JWK{
    // 生成token
    public static function create_token($header,$payload,$secret){
        $header_str = self::encode($header);
        $payload_str = self::encode($payload);
        $jwt_str = $header_str.'.'.$payload_str;
        return  $jwt_str.'.'.self::create_signature($jwt_str,$secret,$header['alg']);
    }
    // 编码
    public static function encode($json){
        return base64_encode(json_encode($json));
    }   
    // 解码
    public static function decode($content){
        return json_decode(base64_decode($content),true);
    }
    // 创建签名
    public static function create_signature($jwt_str,$secret,$type){
        return hash($type,$jwt_str.'.'.$secret);
    }
    // 验证签名
    public static function check_signature($str,$secret){
        $arr = explode('.',$str);
        if( count($arr)===3 ){  
            $header = self::decode($arr[0]);
            $signature =  self::create_signature($arr[0].'.'.$arr[1],$secret,$header['alg']);
            if( $signature===$arr[2] ){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }
    // 获取结果
    public static function get_result($str){
        $arr = explode('.',$str);
        if( count($arr)===3 ){
            return [
                'header'    => self::decode($arr[0]),
                'payload'   => self::decode($arr[1]),
                'signature' => $arr[2]
            ];
        }else{
            return false;
        }

    }
}


$secret = '464646413132aaa';
$header = [
    'alg' => 'sha256',
    'uid' => '1',
];
$payload = [
    'name'      => 'ricky',
    'content'   => 'nobody'
];

// 创建token    只要攻击者不知道secret是无法伪装token的,所以secret必须保护好
$token = JWK::create_token($header,$payload,$secret);

// 验证token签名
if( JWK::check_signature($token,$secret) ){
    // 获取解码token内容
    if( $res = JWK::get_result($token) ){
        echo json_encode($res);
    }
    
}

 

posted @ 2018-10-28 10:57  Ricky_boke  阅读(336)  评论(0编辑  收藏