This article shares with you how to refresh tokens in Vue. The content is very good. Friends in need can refer to it. I hope it can help everyone.
token authentication mechanism
After the client login request is successful, the server encrypts the user information (such as user ID) using a special algorithm and sends it to the user as a verification sign. (i.e. token), when the user initiates a request next time, this token will be brought over, and the server will decrypt the token for verification. If it passes, the requested data will be returned to the client; otherwise, the request will fail.
Advantages of token
It is stateless, and the server does not need to save session information like traditional identity authentication (session), which reduces the pressure on the server.
vue’s token refresh processing
After a brief introduction to the token authentication mechanism, enter the text...
General For the sake of security, the token will set an expiration time. After the expiration, the relevant interface cannot be requested. What should I do at this time? Should I log out directly?
In the current company's project, for a better user experience, we choose to refresh the token manually. After the login request is successful, a token and the token expiration time will be returned. Each time the API is requested, the front end can first determine whether the token is about to expire or has expired. If so, request the interface to refresh the token. After successfully replacing the original token Only then can the request be reinitiated.
Next, let’s look at the code directly. This is the relevant operation performed in vue’s request interceptor:
/*是否有请求正在刷新token*/ window.isRefreshing = false /*被挂起的请求数组*/ let refreshSubscribers = [] /*获取刷新token请求的token*/ function getRefreshToken () { return JSON.parse(localStorage.auth).refresh_token } /*push所有请求到数组中*/ function subscribeTokenRefresh (cb) { refreshSubscribers.push(cb) } /*刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)*/ function onRrefreshed (token) { refreshSubscribers.map(cb => cb(token)) } /*请求拦截器*/ ajax.interceptors.request.use( config => { const authTmp = localStorage.auth /*判断是否已登录*/ if (authTmp) { /*解析登录信息*/ let auth = JSON.parse(authTmp) /*判断auth是否存在*/ if (auth) { /*在请求头中添加token类型、token*/ config.headers.Authorization = auth.token_type + ' ' + auth.token /*判断刷新token请求的refresh_token是否过期*/ if (util.isRefreshTokenExpired()) { alert('刷新token过期,请重新登录') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return } /*判断token是否将要过期*/ if (util.isTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { /*判断是否正在刷新*/ if (!window.isRefreshing) { /*将刷新token的标志置为true*/ window.isRefreshing = true /*发起刷新token的请求*/ apiList.refreshToken({refresh_token: getRefreshToken()}).then(res => { /*将标志置为false*/ window.isRefreshing = false /*成功刷新token*/ config.headers.Authorization = res.data.data.token_type + ' ' + res.data.data.token /*更新auth*/ localStorage.setItem('auth', JSON.stringify(res.data.data)) /*执行数组里的函数,重新发起被挂起的请求*/ onRrefreshed(res.data.data.token) /*执行onRefreshed函数后清空数组中保存的请求*/ refreshSubscribers = [] }).catch(err => { alert(err.response.data.message) /*清除本地保存的auth*/ // localStorage.removeItem('auth') window.location.href = '#/login' }) } /*把请求(token)=>{....}都push到一个数组中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}这个函数就是回调函数*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*将请求挂起*/ resolve(config) }) }) return retry } } return config } else { /*未登录直接返回配置信息*/ return config } }, /*错误操作*/ err => { return Promise.reject(err) } )
There are a few points to note here:
1. When the token is about to expire or has expired, in principle, we only need an interface to trigger a request to refresh the token. The isRefreshing variable here plays a monitoring role, which is equivalent to a handful of Lock, when the operation of refreshing the token is triggered, other trigger operations are excluded.
window.isRefreshing = false
2. The refresh token interface uses another token (refresh_token), which is also for security reasons, and it also has an expiration time, but this expiration time is generally longer than the expiration of ordinary tokens. It takes a long time, so in the above code, you will find that in the request interception, I first determine whether the refresh_token has expired. If it expires, I will log out directly without proceeding to the next step.
/*判断刷新token请求的refresh_token是否过期*/ if (util.isRefreshTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { alert('刷新token过期,请重新登录') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return }
3. After triggering the operation of refreshing the token, we need to suspend other requests first, and then re-initiate these requests after obtaining the new token.
/*把请求(token)=>{....}都push到一个数组中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}这个函数就是回调函数*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*将请求挂起*/ resolve(config) }) }) return retry
Execute the following code in the successful callback of the refresh token request and reinitiate the request.
/*执行数组里的函数,重新发起被挂起的请求*/ onRrefreshed(res.data.data.token)
4. Because someone asked about the util file in the comments, they probably want to know how to determine the token expiration. In fact, when obtaining the token, a token expiration time is returned. You can save it first. Get it up, and then when needed, take it out and compare it with the local time
/*判断token是否过期*/ function isTokenExpired() { /*从localStorage中取出token过期时间*/ let expiredTime = new Date(JSON.parse(localStorage.auth).expired_at).getTime() / 1000 /*获取本地时间*/ let nowTime = new Date().getTime() / 1000 /*获取校验时间差*/ let diffTime = JSON.parse(sessionStorage.diffTime) /*校验本地时间*/ nowTime -= diffTime /*如果 < 10分钟,则说明即将过期*/ return (expiredTime - nowTime) < 10*60 }
Related recommendations:
Specific analysis of SFC and vue-loader in Vue
How to pass values between vue parent and child components
The above is the detailed content of How to refresh token in vue. For more information, please follow other related articles on the PHP Chinese website!