1- Implementation background
The previous implementation of token refresh scheme is to set a timer for a fixed time when the project is running or refreshing, and then inside the timer is the interface that requests token refresh and calls the current timer method again. This method seems to have no problem, but there is a token time that cannot be overridden. Ep: Sets the token expiration time to 5 minutes. We obtained the token upon successful login and set a 4.5min timer to refresh periodically. After 3min, we will perform a refresh operation. At this time, the whole project will run again, and the countdown of 4.5min will be recalculated. However, only 1.5 minutes remain before the token expiration, and the token refresh timer will be executed in 4.5 minutes. Within 4.5min-1.5min=3min, any request sent will be returned to 401 for re-login.
2- Solution
The main problem with the appeal scheme is that the timer is written to death, so it can’t cope with erratic refresh operations. The solution can emulate the cookie and add an Expries parameter to obtain the expiration time of the token at any time. In this way, we can set an adjustable timer according to the Expries parameter no matter the login is successful or the refresh operation is performed, so that the problem of overwriting will not occur. Ep: Sets the token expiration time to 5 minutes. We save the token and the current timestamp, and set a timestamp -30s timer so that the token will be refreshed 30 seconds before the token expires. When performing the refresh operation, repeat the above steps to realize that the timer countdown is adjustable.
3- Concrete implementation
LocalStorage supports strings only and does not support adding attached attributes, so we need to manually encapsulate them.
import api from "@/utils/request.js"
import { message } from "antd"
/ / save the token
export function saveToken(token) {
// Server expiration in 5 minutes The local storage expires in 4.5 minutes
const expries = new Date().getTime() + 4.5 * 60 * 1000
const obj = { token, expries }
window.sessionStorage.setItem("informationToken".JSON.stringify(obj))
}
/ / delete the token
export function delToken() {
window.sessionStorage.removeItem("informationToken")}/ / query token
export function getToken() {
const obj = JSON.parse(window.sessionStorage.getItem("informationToken"))
return obj ? obj.token : ""
}
/ / refresh token
export async function refreshToken() {
// Read the expiration time
const { expries } = JSON.parse(
window.sessionStorage.getItem("informationToken"))const isExpries = expries - new Date().getTime()
console.log('🚀 ~ Time to refresh the token and${isExpries / 1000}Second `)
if (isExpries > 0) {
setTimeout(async() = > {const res = await api.post("/login/fresh")
saveToken(res.token)
refreshToken()
}, isExpries)
} else {
message.error("Your login authentication has expired, please login again!")
setTimeout(() = > {
window.location.href = "/login"
}, 3 * 1000)}}Copy the code
over