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