以后我的项目 JWT 登录鉴权办法及问题
以后登陆鉴权办法
用户登录时,返回一个 JWT,由前端存储在本地。尔后用户每次向须要权限的 API 发出请求时带上该 JWT 用于验证身份。
后端收到 JWT 后,验证 JWT 是否正确且未过期:
- 如果正确且未过期,则返回资源。
- 如果不正确,则返回不正确的状态码;如果已过期,则返回已过期的状态码,要求从新登录。
问题
应用 JWT 实现登录鉴权时,因为 JWT 有固定的过期工夫,可能在用户正在进行操作的过程中恰好过期,而后忽然跳转到登录界面,造成较差的用户体验。
指标
应用 JWT 实现登录鉴权,当且仅当用户在一段时间内不对系统进行任何操作时才要求用户从新登录,并且尽可能保障 JWT 的安全性。
解决办法及优缺点剖析
解决办法一:只应用一个 JWT token(不举荐)
具体实现
用户登录时,返回一个 JWT,由前端存储在本地。尔后用户每次向须要权限的 API 发出请求时带上该 JWT 用于验证身份。
后端收到 JWT 后,验证该 JWT 是否正确:
- 如果不正确,则间接返回错误代码;
-
如果正确,则验证该 JWT 是否过期:
- 如果没有过期,则间接返回资源;
-
如果过期,则计算过期工夫:
- 如果过期工夫没有超过某阈值,则返回资源和新的 JWT;
- 如果过期工夫超过某阈值,则返回错误代码。要求从新登录。
长处
实现了当且仅当用户在一段时间内不对系统进行任何操作时才要求用户从新登录。
当 JWT 过期时如果用户还在操作系统,会向后端发送刚刚过期的 JWT,此时 JWT 的过期工夫没有超过阈值,间接返回资源和新的 JWT,实现用户无感书最新。
然而如果当 JWT 过期之后的一段时间(阈值内)用户都没有操作系统,当用户再次操作系统时,会向后端发送过期工夫超过阈值的 JWT,后端会返回错误代码,实现从新登录。
毛病
安全性较低。如果频繁发送申请,能够应用一个 JWT 实现永恒登录。一旦 JWT 被窃取,攻击者能够应用失去的 JWT 永恒伪造用户获取信息。
解决方案二:应用两个 JWT token(举荐)
具体实现
用户登录时,返回两个 JWT(access token 和 refresh token),一个用于在申请资源验证身份的 access token,一个用于在 access token 过期时更新 access token 的 refresh token。其中 refresh token 的有效期较长(如 7 天),而 access token 的有效期较短(如 1 小时)。由前端存储在本地。尔后用户每次向须要权限的 API 发出请求时带上 access token 用于验证身份。
后端收到 access token 后:验证该 access token 是否正确:
- 如果不正确,则间接返回错误代码;
-
如果正确,则验证该 access token 是否过期:
- 如果没过期,则间接返回资源;
-
如果过期,则返回过期的错误代码。前端收到过期错误代码后应用 refresh token 向更新接口申请新的 access token,更新接口判断 refresh token 是否过期:
- 如果没有过期,则返回新的 access token 和新的 refresh token,将之前所有由同一 refresh token 生成的 refresh token 都置为有效(保护一个有效列表)。前端应用新的 access token 从新向须要权限的 API 发出请求,获取资源。
- 如果过期,则返回错误代码,要求从新登录。
- 如果收到已被置为有效的 refresh token,则将以后所有与有效 refresh token 为同一用户的 refresh token 和 access token 都置为有效(具体来说是将该用户的拜访置为有效),直到用户从新登录。
应用这种办法,既能防止在用户操作的过程中呈现忽然跳转登录(次要解决了两次操作之间的不统一景象,不会呈现一次申请还能失常获取资源,下一次申请资源就忽然跳转到登录页面的景象),又能保障较高的安全性。
解释
Q:为什么不应用永恒无效的 refresh token?
A:为了实现更高的安全性。永恒无效的 refresh token 一旦被窃取,攻击者能够应用该 token 永恒假冒用户获取个人信息。而每次应用 refresh token 就更换一个新的 refresh token 的话,即便 refresh token 被窃取,也会在肯定工夫内生效,攻击者应用的工夫无限。
Q:为什么 refresh token 获取新的 access token 时须要同时更新 refresh token?
A:因为如果不更新 refresh token 的话,就无奈防止用户两次操作之间的不一致性。可能用户在 refresh token 过期前一分钟还能失常操作,一分钟后就忽然跳转到登录页面,造成不敌对的用户体验。
Q:为什么要在应用 refresh token 取得新的 access token 和 refresh token 后将用于申请新 token 的 refresh token 置为有效?
A:为了防止之前的 refresh token 被窃取后导致的重放攻打(应用之前的 refresh token 申请新的 access token 和 refresh token)。
Q:为什么更新接口在收到已置为有效的 refresh token 后会将所有应用第一个 refresh token 失去的 refresh token 都禁止?
A:因为不晓得被窃取的是哪个 refresh token。有可能攻击者应用第一个 refresh token,并应用该 token 在更新接口获取了新的 refresh token,此时用户可能应用旧的 refresh token(已被置为有效)申请更新接口。也有可能攻击者窃取到第一个 refresh token 后,用户首先应用该 token 在更新接口获取了新的 refresh token,此时攻击者可能应用旧的 refresh token(已置为有效)申请更新接口。详见:auth0-refresh-token-rotation
Q:如何在禁止一个 refresh token 时将对应的 access token 置为有效?
A:
- 缩短 JWT 的无效工夫,而后禁止 refresh token:然而 access token 最短也有一个固定的有效期限(5~10min),可能给攻击者提供 5~10min 应用该 token 的工夫。
- 保护一个 blacklist:当一个 refresh token 被禁止时将该音讯播送到所有无关的服务器,所有的服务器保护一个 refresh token 被禁止的用户列表,每次接到一个 access token 时,判断其对应的 refresh token 是否被禁止,如果是就间接返回谬误状态码。
- 详见:fusionauth-revoking-jwts
JWT VS Session:登录鉴权如何选
二者都是为了在无状态的 HTTP 协定中记录登录状态,以防止每次申请都要验证身份。
Session 实现登录鉴权
用户登录胜利后,服务器生成一个对应的 session ID,存储在(内存里的)文件或数据库中,并且放在 cookie 中返回给浏览器。登录后每次申请会发送 cookie,在服务端的存储中查找 cookie 中的 session ID 以验证用户身份。
比照
-
(程度)扩展性:当用户量增大时,须要应用多台服务器解决拜访。
- 如果应用 session,须要解决服务器端存储 session ID 的问题,因而须要一个集中的 session 存储器,个别是一台专门用于运行 redis 的服务器。然而这样也会面临访问量瓶颈的问题。并且同时在线人数过多时须要存储大量 session ID,从而占用大量服务器资源。
- 如果应用 JWT,就不必在服务端存储每个用户的登录信息(除了还未过期但被禁用的 refresh token,然而不必在用户申请业务接口时验证,只用在更新 token 时验证,不会影响业务接口的响应工夫)。任何一台服务器都能间接通过 JWT 判断是否是非法的登录用户。
- 性能:如果 JWT 中蕴含了很多数据,则它会远大于一个 session ID,会给 HTTP 申请带来额定的开销。然而 session 每次都要查找一次数据库来验证用户身份。
-
在服务端破除 session/token(如用户批改明码后破除原来的 session/token):
- 如果应用 session:比较简单,间接从数据库中删除 session ID 即可。
- 如果应用 JWT:比较复杂。因为 token 一旦签发,在有效期内都能被服务器认证。须要保护一个被禁用的 access token 的 blacklist,申请业务接口时查找。
-
在服务端禁止用户:
- 如果应用 session:比较简单,间接从数据库中删除 session ID 即可。
- 如果应用 JWT:比较复杂。因为 token 一旦签发,在有效期内都能被服务器认证。禁止用户须要禁用用户所有还在有效期内的 access token 和 refresh token。须要保护一个被禁用用户的 blacklist,申请业务接口 / 更新 access token 都要查找。
参考
- 基于 JWT+Refresh Token 的用户认证实际
- auth0 refresh token
- auth0 refresh token rotation
- 是抉择长时间的 access token 还是短时间的 access token+ 刷新
- 破除有效 JWT
- JWT 与 Session
- JWT 禁用问题