

前端如何实现token的无感刷新
source link: https://segmentfault.com/a/1190000040850857
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前端如何实现token的无感刷新
通常,对于一些需要记录用户行为的系统,在进行网络请求的时候都会要求传递一下登录的token。不过,为了接口数据的安全,服务器的token一般不会设置太长,根据需要一般是1-7天的样子,token过期后就需要重新登录。不过,频繁的登录会造成体验不好的问题,因此,需要体验好的话,就需要定时去刷新token,并替换之前的token。
要做到token的无感刷新,主要有3种方案:
后端返回过期时间,前端每次请求就判断token的过期时间,如果快到过期时间,就去调用刷新token接口。
缺点:需要后端额外提供一个token过期时间的字段;使用了本地时间判断,若本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败。
写个定时器,然后定时刷新token接口。
缺点:浪费资源,消耗性能,不建议采用。
在请求响应拦截器中拦截,判断token 返回过期后,调用刷新token接口。
综合上面的三个方法,最好的是第三个,因为它不需要占用额外的资源。接下来,我们看一下使用axios进行网络请求,然后响应service.interceptors.response的拦截。
import axios from 'axios' service.interceptors.response.use( response => { if (response.data.code === 409) { return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => { const { token } = res.data setToken(token) response.headers.Authorization = `${token}` }).catch(err => { removeToken() router.push('/login') return Promise.reject(err) }) } return response && response.data }, (error) => { Message.error(error.response.data.msg) return Promise.reject(error) } )
问题一:如何防止多次刷新token
为了防止多次刷新token,可以通过一个变量isRefreshing 去控制是否在刷新token的状态。
import axios from 'axios' service.interceptors.response.use( response => { if (response.data.code === 409) { if (!isRefreshing) { isRefreshing = true return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => { const { token } = res.data setToken(token) response.headers.Authorization = `${token}` }).catch(err => { removeToken() router.push('/login') return Promise.reject(err) }).finally(() => { isRefreshing = false }) } } return response && response.data }, (error) => { Message.error(error.response.data.msg) return Promise.reject(error) } )
二、同时发起两个或者两个以上的请求时,怎么刷新token
当第二个过期的请求进来,token正在刷新,我们先将这个请求存到一个数组队列中,想办法让这个请求处于等待中,一直等到刷新token后再逐个重试清空请求队列。
那么如何做到让这个请求处于等待中呢?为了解决这个问题,我们得借助Promise。将请求存进队列中后,同时返回一个Promise,让这个Promise一直处于Pending状态(即不调用resolve),此时这个请求就会一直等啊等,只要我们不执行resolve,这个请求就会一直在等待。当刷新请求的接口返回来后,我们再调用resolve,逐个重试。
import axios from 'axios' // 是否正在刷新的标记 let isRefreshing = false //重试队列 let requests = [] service.interceptors.response.use( response => { //约定code 409 token 过期 if (response.data.code === 409) { if (!isRefreshing) { isRefreshing = true //调用刷新token的接口 return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => { const { token } = res.data // 替换token setToken(token) response.headers.Authorization = `${token}` // token 刷新后将数组的方法重新执行 requests.forEach((cb) => cb(token)) requests = [] // 重新请求完清空 return service(response.config) }).catch(err => { //跳到登录页 removeToken() router.push('/login') return Promise.reject(err) }).finally(() => { isRefreshing = false }) } else { // 返回未执行 resolve 的 Promise return new Promise(resolve => { // 用函数形式将 resolve 存入,等待刷新后再执行 requests.push(token => { response.headers.Authorization = `${token}` resolve(service(response.config)) }) }) } } return response && response.data }, (error) => { Message.error(error.response.data.msg) return Promise.reject(error) } )
Recommend
-
35
如题,本节我们进入JWT最后一节内容,JWT本质上就是从身份认证服务器获取访问令牌,继而对于用户后续可访问受保护资源,但是关键问题是:访问令牌的生命周期到底设置成多久呢?见过一些使用JWT的童鞋会将JWT过期时间设置成很长,有的几个小...
-
24
图片来源@unsplash 文|刘志刚 1998年约瑟夫.派恩和詹姆斯.吉尔莫(Joeph Pine和James Gimore)在哈佛商业评论上的一篇文章...
-
27
10月24日,一年一度的“白帽黑客”对决盛会GeekPwn2020国际安全极客大赛在上海举办,来自腾讯的参赛队伍Blade Team亮相赛场,并成功实现了对“无感支付”式直流充电桩的漏洞攻击演示。
-
34
10年前出现的4G,曾带来了移动互联网的飞速发展,真实与虚拟的界限被模糊,人们在新技术网织出的消费互联网中乘风破浪,也见证了一批批创...
-
11
axios如何利用promise无痛刷新token 本文共有8146个字,关键词:axios、
-
14
动铁单元小幅升级无感延迟小捷Air Plus体验-手机中国论坛 [其他] 动铁单元小幅升级无感延迟小捷Air Plus体验
-
13
访问令牌(access token)和刷新令牌(refresh_token )酱油瓶20.1412019.07.15 18:54:15字数 256阅读 2,9621、token化的协议过程
-
7
最近为了赶进度加班越来越频繁,位置上一坐就是十多个小时,导致近来腰酸背痛的症状愈发明显,严重影响身体活动,以及工作进度。遂告病假检查,结果为腰肌劳损。建议多卧床休息,然而卧床休息对于996的我来说过于奢侈了点,得,日子还得过下去。
-
4
祝融说。 广告应该是无感的,它应该是内容的一部分,甚至独自就能成为一种内容。 祝融说。
-
172
Victrid's Personal SiteThis website uses cookies to provide better contents. Check our privacy policy.OK 一直让我不解的是,我的整个博客只有
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK