JWT 是什么
JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象安全传输信息。这些信息可以通过数字签名进行验证和信任。
JWT 的组成
JWT 的格式为 xxx.yyy.zzz。
包含 Header(头部),Payload(负载),Signature(签名)三部分。
Header
通常会声明使用的加密算法和token类型1
2
3
4{
"alg": "HS256",
"typ": "JWT"
}Payload
Payload 包含 Claims,Claim是一些实体(一般都是用户)的状态和额外的数据组成。
JWT 为我们预定义了一些 Claims,例如:iss (issuer), exp (expiration time), sub (subject), aud (audience), and others.
但是并不要求我们强制使用,我们也可以根据需求自定义 Claim1
2
3
4
5{
"sub": "1234567890",
"name": "Taven",
"admin": true
}Signature
1
2
3
4HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
这段伪代码已经很好的讲解了,签名是如何计算的。服务端提供一个secret,将header、payload 进行base64编码,然后使用header中声明的算法计算签名。
JWT 与 session 对比
- 性能:JWT 轻量级,而session 会占用大量服务端内存;
- 部署:使用session的系统 负载均衡需要考虑 session 共享,而JWT 不需要;
- 安全:安全性的话,小弟不敢多说,我觉得五五开吧,有人说 JWT 泄露的话,直接就可以登录了。但是使用 session 如果请求被拦截了都是一样的;
- 场景:APP 中由于没有cookie吧,多是使用token。而 web 应用的话,使用 token 和 session 都是可以的。
实现思路
简单一句话就是,登录之后服务端给客户端颁发JWT,客户端将 JWT 放在请求头中,服务端 filter 校验http header中的JWT。
查阅了一些资料后发现一些分歧
方案1: 有的朋友认为服务端不需要存储 JWT,只在 filter 校验的时候解析无误,即认为 JWT 是可用的。在需要重置 JWT 的时候(例如注销),客户端主动删除JWT。这种做法引发的问题,例如在注销了之后,token 依然可用,由于服务端没有存储 token,无法去校验。于是乎有了方案2
方案2:服务端数据库中存储 JWT,filter 每次校验 token 与数据库中是否一致,这种做法虽然稳妥,但是在性能上一定是不如方案1的。
demo
https://gitee.com/yintianwen7/taven-springboot-learning/tree/master/spring-boot-jwt