大家好,我是此林。
尽管JWT是大家再熟悉不过的东西了,但是温故而知新,还是有必要详解下。
目录
1. 两种身份认证对比
1. 有状态身份认证
2. 无状态身份认证(JWT)
2. JWT组成
1. Header
2. payload
3. signature
3. 服务端校验
4. 优缺点
1. 两种身份认证对比
1. 有状态身份认证
客户端保存令牌(可以是随机字符串),客户端携带令牌访问服务器,服务器拿着令牌到(本地内存 / 数据库 / Redis)中寻找是否存在相关用户信息。如果有,通过放行;没有,拒绝访问。
2. 无状态身份认证(JWT)
服务器不保存用户信息,单纯从令牌校验。请看下文。
2. JWT组成
JWT由三部分组成:Header,payload,signature。
1. Header
包含:加密算法(一般是HS256对称加密算法),type(固定字符串,一般是“JWT”,不用管这个type)
header本质上就是个键值对。
Header用base64编码后得到如下字符串。
2. payload
也是个键值对。
包含:
1. 自定义用户信息,可以是username,role等。
2. JWT令牌的签发时间。
3. JWT令牌的过期时间。
4. JWT令牌的生效时间。
payload用base64编码后如下:
因为base64可以反编码,所以payload不要存储用户敏感信息。
3. signature
公式:HS256(baseUrl64(header) + "." + baseUrl64(payload) + "." + secret_key))
secret_key是自定义密钥,不能泄露。
最终生成的JWT令牌:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJwYXNzd29yZCI6IjEyMzQ1NiIsIm5iZiI6MTczNjQzNTAzMiwiZXhwIjoxNzM2NDM2ODMyLCJpYXQiOjE3MzY0MzUwMzIsInVzZXJuYW1lIjoiYWRtaW4ifQ
.FlPC86hcT1mLE060MBkTlbjB6l-2EqXBRqVfBxMSa14
可以看到这里JWT由三个点分隔开,分别对应header,payload,signature。
3. 服务端校验
1. 服务端解析Token,取出header和payload,结合加密算法和secret_key生成签名。
2. 服务端把这个生成的签名和用户传来的Token中的signature比对,看是否相等。
3. 若相等,则令牌合法(没有被篡改过)。
4. 服务器再去payload中取出相关的签发时间,过期时间,生效时间,校验令牌是否过期或有效。
5. 若时间上都合法,那么Token有效,放行。
4. 优缺点
优点:
1. 无状态性,用户信息无需保存服务端,方便服务端集群部署或水平扩展。
缺点:
1. JWT令牌比较长,占用空间大,网络传输消耗资源多。
2. 因为无状态性,令牌一旦颁发后,在过期之前一直都保持有效。导致:无法踢人下线、用户权限更改后无法立刻生效。
解决方案:
1. 不使用JWT模式,使用有状态身份认证,即用户信息保存在本地或Redis中。
2. 维护一份JWT令牌黑名单,可以选择保存在Redis中,过期时间设置为令牌过期时间。用户携带JWT令牌访问时,先查看Token是否在黑名单中,没有再进行进一步校验合法性和是否过期;否则,拒绝访问。