JWT避坑指南(遇坑无数,持续更新,希望对新手有用)

本文不画图,不秀 code, 只讲一些概念上的东西, 防止大家误入歧途。
当然水平有限,有错误之处,请多指正,勿喷。

1 最重要的,不要考虑在服务器维护 JWT

Session是把用户认证信息放在服务器管理,JWT则是拿到了客户端,如果再在服务器维护JWT,不如直接用Session,若支持非Web客户端,手写个类Web Session的机制来管理客户端也不是难事,加上还有Redis加持。

理解这一点,能少走很多弯路。只要有在服务器维护JWT的念想,就直接干掉吧,比如:

  • 在服务器端维护一个 JWT token 黑名单。

2 鱼与熊掌不可兼得

2.1 Web Session 方案

优点

  • 自动续期
  • 在线用户列表
  • 踢人下线
  • 并发登录控制等

缺点

  • 依赖 Cookie
  • CSRF攻击(有解决方案)
  • 扩展性问题(spring session + redis)
  • 传说中的性能问题

2.2 JWT Session 方案

优点

  • 不依赖 Cookie,支持各种客户端
  • 自包含(自带防篡改的用户身份信息,比如Payload中存一个用户id或uuid)
  • 服务器存取Session的资源得以释放
  • JSON格式通用,支持各种语言

缺点

  • 看Session优点中的几个问题
  • 用户状态变化(删除,禁用,注销等)影响到业务而Token仍然有效时

3 几个应该知道的

  • JWT是防篡改的,不能通过修改他的过期时间(exp) 来实现续期,一量修改,其实是生成了一个新的 Token
  • 每次请求返回一个新的JWT token 虽然能“解决”续签问题,不说性能上的损耗,光这种做法就觉得不是正确的

4 使用 JWT,几个最佳实践

如果能容忍 JWT 的缺点,采用 JWT,以下是几个比较好的实践

使用 accessToken + refreshToken

  • 认证后,返回 accessToken + refreshToken,并保存在本地, Web下推荐 HttpOnly cookie
  • accessToken 使用 JWT 格式
  • refreshToken 使用 UUID, 并维护在服务器端(使用得较少),不用 JWT (原因见第一大点)
  • accessToken 失效时间应该设置较短,比如10分钟
  • refreshToken 失效时间可以长一点,比如 7 天
  • 请求时只用 accessToken
  • accessToken 失效时,用 refreshToken 返回一个新的 accessToken(刷新 token)
  • 刷新 token 时可对 refreshToken 做自动续期,提高用户体验
  • 最好在 accessToken 在失效前主动 refreshToken
  • 避免同时发送多个 refreshToken 请求

JWT 续签问题

  1. 客户端主动续签
    客户端搞个线程定时主动检查Token过期时间,在过期前 (例如过期前1分钟) refresh一下Token

  2. 服务器端每次都续签
    这个前面讲过,只是一种方法,但太不优雅

  3. 服务器端在Token过期前(例如过期前1分钟)续签
    这个其实比较难掌控,假过期前1分内,客户端没有发请求,就续签不了,眼巴巴看着 session 过期,如果设置得过长,那么前面一个Token还会在相当长的时间内有效。而且假如一个 page 有10个请求同时过来,都达到刷新时间,那么会刷10次,最只有最后一次的起作用

所有续签的话,还是推荐客户端主动续签。

用户注销

用户点击注销,删除客户端 token。如果直接关客户端,只有等 accessToken过期

用户修改密码/禁用用户/删除用户

这几种情况在Session环境中可以更新/失效 session来达到安全要求,
但JWT不行,有效期内的accessToken会通过第一道验JWT的关卡,如果没有第二道验 user 的关卡,就直接通过去做业务逻辑了。

5 关于安全方面,几个认识和实践

  • 使用 https保护你的应用
  • sessionid 和 accessToken 泄露,造成的影响是一样,没有哪个更安全 (所以说 accessToken失效时间越短越安全)
  • 不要在payload中不应该存放敏感信息,这部分客户端是可以解密的。
  • secret_key 放在服务器端,不能泄露。

6 JWT 的使用场景

适合的

  • OneTime Token
  • App Token

不适合的

  • 替代 Session 管理
  • 单点登录

6 BFF, 了解下?

  • 不要设计成让所有类型的客户端调用相同的 API Servers
  • 不同的Front 调用不同的Backend For Frontend Server
  • 那么 WebServer用Session不香么

先写这么多,待补充。

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页