登录认证最佳实践:基于双令牌的无感刷新机制(保姆级教程,支持 XSS 防护 + 高并发优化)

78 阅读2分钟

登录认证:

token双令牌(无感刷新)

无感刷新:用户访问一个网页,只要在七天内有操作,就不需要重新登陆,登录的token就一直被更新,但如果七天都没有任何操作,那就需要重新登陆

仅后端实现:后端每个接口都自定给token续期(token续期过于频繁,高并发下服务器压力大,而且不安全,一旦被捕获但token且拿到接口,岂不是能无限续签)

仅前端实现,后端给token的时间戳(expireTime),告诉前端到期时间,快到期时前端请求给token续期(不足够安全,可能被篡改,依赖客户端控制)

双令牌实现:

access_token短令牌,几个小时的有效期,refresh_token长令牌,好几天的有效期,

所有接口都通过携带access_token判断有无权限,

access_token过期,发起token续期的请求(携带refresh_token作为参数),后端判断refresh_token是否过期,

refresh_token未过期,生成新的refresh_token(每生成一个新的就有好几天有效期,如果一直使用,可以一直延续)和accsess_token给前端,

若refresh_token过期,返回登录过期给前端,前端需要提示用户重新登陆

值得注意的一点是,为了安全,一般不会把access_token放到localStorage,而是存储在 HTTP-only Cookie 中

由后端实现

那么前端如何在请求token续期时取到refresh_token呢?

只需要在发送请求时,config设置withCredentials: true

关于XSS攻击:

refresh_token存储在HTTP-only Cookie 中,通过document.cookie是取不到的,因此xss攻击无效!!!

关于token双令牌的优化:

由于我们关于token续期的逻辑是在请求中封装的,那么一旦用户在access_token失败时发起多个请求,那岂不是会触发多个续签请求?

优化!必须优化!

设置一个请求队列queue,有n个请求都是执行一样的目的

那么只要第一个请求和服务器建立连接了,其他请求都是去队列里等待。

这个请求成功了,告诉其他请求我成功了;

这个请求失败了,告诉其他请求我失败了;

其实不管成功还是失败,最后任务队列都是要被清空的,里面的请求注定无法发送。

参考博文:

juejin.cn/post/727113…

juejin.cn/post/742321…

juejin.cn/post/747815…