JWT简介
JWT
( $JSON\ \ Web\ \ Token$ )是一种基于JSON
的用于创建可选签名或可选加密的数据的互联网标准。Token
使用一个私钥或者公钥进行签名,持有私钥或者公钥的一方可以验证令牌的合法性。Token
被设计为紧凑且安全的,尤其适用于Web
浏览器单点登录 ( Single-sign-on
, $SSO$ ) 场景。JWT
声明一般用于在身份提供者和服务提供者之间传递用户身份信息,或者用于业务流程要求的任何其他类型的声明。
在传统的session
认证中,通常使用cookie
来保存用户的身份信息,方便下一次请求。由于session
是存储在内存中的,因此存在开销隐患。而且使用cookie
也意味着存在着CSRF
问题。使用JWT
进行认证时,用户在成功认证登录过后,将会得到一个token
。Token
会保存在本地(也可以保存在session
或者cookie
中),而不是传统的在服务器上创建一个session
并返回cookie
。每当用户想要访问受保护的资源时,用户代理需要发送JWT
,JWT
通常包含在请求头中。通过使用JWT
,用户的状态永远也不会保存在服务器中。当接收到请求时,服务器将会检查JWT
的有效性。由于JWT
是独立的,存储着所有必要的信息,因此可以减少数据库查询的次数。
JWT
的结构
JWT
由三部分组成:$Header$, $Payload$, $Signature$ 。
1. Header
{
"alg": "HS256",
"typ": "JWT"
}
$Header$ 标识用于生成签名的算法。典型的加密算法如HMAC-SHA-256
, RSA-SHA-256
。上例使用的是HMAC-SHA-256
。
2. Payload
{
"loggedInAs": "admin",
"iat": 1422779638
}
$Payload$ 包含了一组声明。JWT
标准注册了七个声明:
- $iss$:
JWT
签发者 - $sub$:
JWT
面向用户 - $aud$:
JWT
接收方 - $exp$:
JWT
过期时间 - $nbf$:
JWT
启用时间 - $iat$:
JWT
签发时间 - $jti$:
JWT
的唯一身份标识,可以用作一次性token
$Payload$ 中还可以添加自定义声明,如上例的 $loggedInAs$。
3. Signature
var signature = HMAC-SHA256(
base64urlEncoding(header) + '.' + base64urlEncoding(payload),
'secret'
);
$Signature$ 用于安全地验证token
。使用 $Base64urlEncoding$ 对 $header$ 和 $payload$ 进行编码,再使用句点隔开,可以计算出签名。$secret$保存在服务器中,在使用指定算法生成签名的时候使用,生成哈希,确保数据不被篡改。然后再通过指定的算法,在此例中为 HMAC-SHA256
, 进行加密。$Base64url$ 编码类似于 base64
。
最终得到的JWT
如下
const token = base64urlEncoding(header) + '.' + base64urlEncoding(payload) + '.' + base64urlEncoding(signature);
最后在请求头中加入
Authorization: `Bearer' + token