JSON Web Token (JWT)
互联网服务离不开用户认证,其中,session 是常见的认证方式,session 在服务端保存相关数据,这种模式的问题在于,扩展性不好:单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session
JWT 是一种跨域认证解决方案,这种方案服务器不保存任何 session 数据,所有数据都保存在客户端,每次请求都发回服务器。也就是说,服务器变成无状态了,从而比较容易实现扩展
JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户。以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名
JWT 结构
JWT 的结构是三部分,用点号连接,分别是 Header、Payload、Signature
写成一行,如下所示:
1 | Header.Payload.Signature |
Header
Header 部分是一个 JSON 对象,描述 JWT 的元数据
1 | { |
alg
属性表示签名的算法,默认是 HMAC SHA256(HS256)
typ
属性表示这个令牌(token)的类型(type),JWT 令牌统一写为 JWT
最后,上面的 JSON 对象会使用 Base64URL 算法转成字符串
Payload
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除了官方字段,还可以在这个部分定义私有字段
1 | { |
该 JSON 对象也会使用 Base64URL 算法转成字符串
JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分
Signature
Signature 部分是对前两部分的签名,防止数据篡改
它会使用前面 Header 里面指明的算法,按照下面的公式生成
1 | HMACSHA256( |
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用 .
分隔,就可以返回给用户
其中,Base64URL 算法是 Base64 的一种变体,具体规则为:base64 的三个字符 =
、+
、/
由于在 URL 里面有特殊含义,所以要被替换掉:=
被省略,+
替换为 -
,/
替换为 _
使用 JWT
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage
以后,客户端每次与服务器通信,都要带上这个 JWT,可以把它放在 Cookie 里面自动发送,但是这样不能跨域
所以更好的做法是放在 HTTP 请求的头信息 Authorization
字段里面
或者跨域的时候,放在 POST 请求的数据体里面发送
JWT 利用
HS256 模式
使用 jwt_tool.py 进行字典破解
1 | 查看JWT内容信息 |
RS256 模式
该模式需要拿到私钥和公钥
利用 private.key 生成签名部分,python脚本如下:
1 | import jwt |
利用 jwt_tool.py 使用 public.key 验证生成签名有效性
1 | python jwt_tool.py [JWT_TOKEN] -V -pk /public.key |
参考
[1]. JSON Web Token 入门教程