JWT令牌介绍
什么是JWT
JWT(JSON Web Token)是一个开放标准,它定义了一种紧凑且独立的方法,用于在各方之间安全地将信息作为JSON对象传输。 由于此信息是经过数字签名的,因此可以被验证和信任。 可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。
JWT令牌结构
三部分组成,每部分中间使用“.”分割开,如:header.payload.signature;
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjMiLCJzdWIiOiIyMGRlYjFjNzNmYzg0ZGQxYjQxZjkzNjM2ZTM4OGM2MyIsImlhdCI6MTYxNjQ4NjAyMCwidXNlcklkIjoiMTIzNDU2MTIzNDY1IiwiZXhwIjoxNjE2NDg2MDIwfQ.P6sR-iKYVyqgq3lyOJeGQRU1gXA91eLMd6yd4QYGxLA
Header
头部包含两部分:
-
加密的算法:HS256
-
类型:JWT
{ "alg": "HS256", "typ": "JWT" }
以上内容使用Base64编码,得到一个字符串组成JWT令牌的header部分,如下:
eyJhbGciOiJIUzI1NiJ9
Payload
负载部分,除了可以存jwt提供的现成字段(如: iss(签发者),exp(过期时间),sub(面向的用户),aud(接收方),iat(签发时间)),也可以存放用户自定义的信息(如:id,name)。但此部分不建议存储敏感数据,因为可以解码出内容。
{
"iss": "start_laosan",
"iat": 1441593502,
"exp": 1441594722,
"aud": "accept_user",
"sub": "face_user",
"id": "202100001",
"name": "gjren"
}
以上内容使用Base64编码,得到一个字符串组成JWT令牌的payload部分,如下:
eyJqdGkiOiIxMjMiLCJzdWIiOiIyMGRlYjFjNzNmYzg0ZGQxYjQxZjkzNjM2ZTM4OGM2MyIsImlhdCI6MTYxNjQ4NjAyMCwidXNlcklkIjoiMTIzNDU2MTIzNDY1IiwiZXhwIjoxNjE2NDg2MDIwfQ
Signature
签名部分,使⽤base64将前两部分进⾏编码,编码后使⽤点"."连接组成字符串,最后使⽤header中声明签名算法进⾏签名,目的防止jwt内容被篡改。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
如下:
P6sR-iKYVyqgq3lyOJeGQRU1gXA91eLMd6yd4QYGxLA
验证
可在网址上进行验证:https://jwt.io/,如下图:
若secret校验失败,左下角会显示:Invalid Signature
JWT使用场景
-
激活账户
比如用户注册后会收到一封激活账户的邮件,该链接就可以理解为一个具有jwt特性的链接:能够识别用户、过期时间短、不能激活其他用户;
-
无状态验证
一次登录获取token后,后续的所有接口调用都使用该token进行校验,在当前服务就可以,无需调用其他服务的接口,提升了性能;
优缺点
优点:
- 无需保存:后端服务不需要存储在数据库或者redis中,只需在登录后将token返回给前台即可,前台对token进行缓存;
- 提升性能:获取token后,对token进行校验在当前服务解析token后就可以校验,减少服务之间交互或者与数据库redis等的交互过程;
缺点
- 不安全:jwt中payload部分使用base64编码,且未解密,所以用户可以解析获取;
- 降低性能:因为jwt格式的token 要比普通的uuid等格式的token更大,很长的字符串,如果存储内容更多,字符串也会更长,因为使用jwt的请求要比session开销更大;
- 无法废弃:一旦生成一个jwt格式的token,该token完全暴露给用户,即使用户被删除或者退出登录,该token还是可以继续使用;
- 无法续签:jwt格式的token生成的过期时间是在Payload部分设置,无法再次对token进行修改续签;
使用注意点
- jwt格式token不要存放敏感信息;
- jwt内容过多会增加网络带宽占用;
Demo实现
- 明儿见;