文章

Token与JWT区别

Token与JWT区别

Token与JWT区别

Token与JWT区别

什么Token?

token是一种令牌。是服务端生成的一串字符串,作为客户端传输的一种表示。

传统的Token验证

客户端第一次访问服务端时,传输用户名和密码,服务端进行一系列验证后生成token返回给客户端。此后,客户端拿着token访问服务端接口,服务端根据token验证授权信息,无需每次都传输用户名和密码。

请求流程

  • 1、客户端发送用户名和密码到服务端。
  • 2、验证成功后,服务端签发token返回到客户端,同时将其保存的数据库或者缓存中。
  • 3、客户端接收到token后将token保存到Cookie 里或者 Local Storage中。
  • 4、当客户端再次访问服务端接口时需传输token。
  • 5、服务端获取token后,需查询数据库或者缓存验证token,成功后返回客户端请求数据。

优点:

  • 1、适用于分布式。
  • 2、安全性高,不会暴露隐私信息。

缺点:

  • 1、由于token无状态,被截取后,别人也能用。
  • 2、需要保存到数据库或者缓存中,占用服务器资源

JWT验证

JWT是 json web token 的缩写。它会将用户的信息保存在json字符串中,经过加密生成一串字符串token、客户端通过传输token,服务端接收到token后进行反解密,验证用户信息。

请求流程

  • 1、客户端发送用户名和密码到服务端。
  • 2、验证成功后,服务端签发token返回到客户端。
  • 3、客户端接收到token后将token保存到Cookie 里或者 Local Storage中。
  • 4、当客户端再次访问服务端接口时需传输token。
  • 5、服务端获取token后,进行反解密获取用户信息成功后返回客户端请求数据。

优点:

  • 1、无需保存在服务器,减轻服务器压力
  • 2、由于应用json,支持跨语言。
  • 3、token内部信息无法被需改,在服务中可以自行解析校验出用户信息,对认证服务器压力小

缺点:

  • 1、jwt生成后无法修改信息。
  • 2、无法做销毁处理。可以一直使用,直到令牌自身失效。
  • 3、最好不要再json中传输隐私信息。
  • 4、令牌长度与其包含用户信息多少正相关,传输开销较大
  • 5、由于token无状态,被截取后,别人也能用。

###

jwt的结构 jwt由3部分组成

1.Header(头) 作用:记录令牌类型、签名算法等 。

1
$header = base64_encode(json_encode(['type'=>'JWT','alg'=>'HS256']))

2.Payload(有效载荷)作用:携带一些用户信息 。

1
2
# {"sub":"1","iss":"http://localhost/auth/login","iat":1451888119,"exp":1454516119,"nbf":1451888119,"jti":"37c107e4609ddbcc9c096ea5ee76c667"}
$payload = base64_encode(json_encode(['userId'=>1,'username'=>'name','exp'=>'过期时间','iat'=>'签发时间'])) 

3.Signature(签名)作用:防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串

1
2
3
4
$tag = 'SHA256';
$input = $header.'.'.$payload;
$signature = '11111';
$signature = base64_encode (hash_hmac($tag,$input,$signature,true));

###
jwt类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
class JWT
{
    /**
     * header
     * @var string[]
     */
    private static $header = [
        'alg' => 'SHA256',
        'type' => 'JWT'
    ];

    /**
     * 有效载荷
     * 规范,但是可以自己定义
     * @var string[]
     */
    private static $payload = [
        'sub' => 'auth',        // 签发人
        'iss' => 'login',        // 主题
        'iat' => '',        // 签发时间
        'exp' => '',        // 过期时间
        'nbf' => '',        // 生效时间。在此之前是无效的
        'jti' => '',        // 编号
    ];

    /**
     * 秘钥
     * @var string
     */
    private static $key = 'ljdfbeuksdhalvnf';

    /**
     * 初始化 载荷
     * @param string $key
     */
    public function __construct(string $key = '')
    {
        if (empty($key)) {
            self::$key = $key;
        }
        self::$payload['iat'] = time();
        self::$payload['exp'] = time() + 86400;
        self::$payload['nbf'] = time();
    }

    /**
     * 获取 JWT
     * @param $data
     * @return string
     */
    public function getToken($data)
    {
        # 填充有效信息
        self::$payload = array_merge(self::$payload, $data);
        # header 加密
        $headerBase = base64_encode(json_encode(self::$header));

        // 载荷加密
        $payloadBase = base64_encode(json_encode(self::$payload));
        $input = $headerBase . '.' . $payloadBase;
        # 生成JWT签名
        $signature = $this->getSignature($input, self::$key, self::$header['alg']);
        $token = $input . '.' . $signature;
        return $token;
    }

    /**
     * 生成JWT签名
     * @param string $input header+payload
     * @param string $key 密钥
     * @param string $alg 加密方式
     * @return string
     */
    protected function getSignature($input, $key, $alg)
    {
        return base64_encode(hash_hmac($alg, $input, $key, true));

    }

    /** 验证
     * @param $token
     * @return mixed|string[]
     */
    public function check($token)
    {
        list($header, $payload, $signature) = explode('.', $token);
        $input = $header . '.' . $payload;
        $newsignature = $this->getSignature($input, self::$key, self::$header['alg']);
        if ($newsignature == $signature) {
            $json = base64_decode($payload);
            $arr = json_decode($json, true);
            return $arr;
        }
        return ['失败'];
    }
}

$data = ['uid' => 1];
$jwt = new JWT('43251');

// 生成token
$token = $jwt->getToken($data);

// 验证
print_r($jwt->check($token));
本文由作者按照 CC BY 4.0 进行授权

© 独行的风. 保留部分权利。

本站采用 Jekyll 主题 Chirpy

本站总访问量 本站访客数 本文阅读量