当我们使用前后端分离的架构时,前端需要向后端服务器发送API请求获取数据,而前端需要在每次请求时,将后端返回的Token设置在请求的Header中。Token是用来验证用户身份的,它的有效期是有限的,过期后需要重新向服务器获取。在这种情况下,我们需要处理Token过期的问题。下面,我将提供一个JS无痛刷新Token的实现的完整攻略:
Step1:在前端存储Token
我们需要在前端存储Token,可以选择将Token存储在SessionStorage或者LocalStorage中。当用户打开网站时,我们需要从SessionStorage或者LocalStorage中获取Token,并将Token设置在请求的Header中。
Step2:拦截HTTP请求
我们需要拦截所有的HTTP请求,检查当前Token是否过期。如果过期了,我们需要刷新Token。
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
Promise.reject(error)
}
)
Step3:处理Token过期
当我们发现Token过期了,我们需要向服务器发送请求,获取新Token。一般来说,我们需要将旧Token发送到服务器,然后让服务器校验Token的有效性并返回新Token。拿到新Token后,我们需要将新Token存储在LocalStorage中,并将Token设置在请求的Header中。
axios.interceptors.response.use(
response => {
return response
},
error => {
const originalRequest = error.config
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
const refreshToken = localStorage.getItem('refreshToken')
return axios
.post('/refresh-token', {
token: localStorage.getItem('token'),
refreshToken: refreshToken
})
.then(response => {
const token = response.data.token
localStorage.setItem('token', token)
originalRequest.headers.Authorization = `Bearer ${token}`
return axios(originalRequest)
})
}
return Promise.reject(error)
}
)
上面的代码使用了axios库来发送Token刷新请求。当我们检测到Token过期时,我们会向服务器发送POST请求,请求体会携带旧Token和RefreshToken。服务器会收到请求后校验Token的有效性,如果无效则返回401状态码。在我们收到401状态码的时候,我们会再次发送Token刷新请求,如果刷新Token成功,我们将新Token存储在LocalStorage中,并将Token设置在请求的Header中,然后重新发起请求。
两条示例
下面提供两条在React项目中实现无痛刷新Token的示例代码:
示例1:
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:3000/api',
})
instance.interceptors.request.use(function (config) {
const token = localStorage.getItem('token')
if (token) {
config.headers.authorization = `Bearer ${token}`
}
return config
})
instance.interceptors.response.use(
function (response) {
return response
},
function (error) {
const originalRequest = error.config
const refreshToken = localStorage.getItem('refreshToken')
if (error.response.status === 401 && originalRequest.url !== '/login') {
if (!originalRequest._retry) {
originalRequest._retry = true
return axios.post('/refresh-token', { refreshToken }).then(({ data }) => {
localStorage.setItem('token', data.token)
localStorage.setItem('refreshToken', data.refreshToken)
axios.defaults.headers.common['authorization'] = `Bearer ${data.token}`
return instance(originalRequest)
})
}
}
return Promise.reject(error)
}
)
export default instance
示例2:
import axios from 'axios'
const axiosInstance = axios.create({
baseURL: 'http://localhost:3000/api'
})
axiosInstance.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => Promise.reject(error)
)
axiosInstance.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config
if (
error.response.status === 401 &&
error.response.data.message === 'Token expired'
) {
const refreshToken = localStorage.getItem('refreshToken')
const res = await axios.post(
'/token/refresh',
{ refreshToken }
)
if (res.status === 200) {
localStorage.setItem('token', res.data.access_token)
localStorage.setItem('refreshToken', res.data.refresh_token)
axiosInstance.defaults.headers.common[
'Authorization'
] = `Bearer ${res.data.access_token}`
return axiosInstance(originalRequest)
}
}
return Promise.reject(error)
}
)
export default axiosInstance
上述两个示例是基于axios库创建的,你可以根据需要选择使用自己喜欢的库。这两个示例实现了当Token过期时,自动刷新Token并重新发送请求的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js无痛刷新Token的实现 - Python技术站