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 进行授权