問題描述
使用 JWT 的 API 請求在 flask 和 Vue.js 中實現.JWT 存儲在 cookie 中,服務器會為每個請求驗證 JWT.
API request using JWT is implemented in flask and Vue.js. The JWT is stored in a cookie, and the server validates the JWT for each request.
如果令牌已過期,將返回 401 錯誤.如果您收到 401 錯誤,請按照以下代碼刷新令牌,再次發出原始 API 請求.以下代碼對所有請求都是通用的.
If the token has expired, a 401 error will be returned. f you receive a 401 error, refresh the token as in the code below, The original API request is made again. The following code is common to all requests.
http.interceptors.response.use((response) => {
return response;
}, error => {
if (error.config && error.response && error.response.status === 401 && !error.config._retry) {
error.config._retry = true;
http
.post(
"/token/refresh",
{},
{
withCredentials: true,
headers: {
"X-CSRF-TOKEN": Vue.$cookies.get("csrf_refresh_token")
}
}
)
.then(res => {
if (res.status == 200) {
const config = error.config;
config.headers["X-CSRF-TOKEN"] = Vue.$cookies.get("csrf_access_token");
return Axios.request(error.config);
}
})
.catch(error => {
});
}
return Promise.reject(error);
});
在令牌過期的情況下同時發出多個 API 請求時無用地刷新令牌.例如,請求 A、B 和 C 幾乎同時執行.由于每個請求都返回 401,每個攔截器都會刷新令牌.
When making multiple API requests at the same time with the token expired Uselessly refreshing the token. For example, requests A, B, and C are executed almost simultaneously. Since 401 is returned with each request, Each interceptor will refresh the token.
沒有真正的傷害,但我認為這不是一個好方法.有一個很好的方法可以解決這個問題.
There is no real harm, but I don't think it's a good way. There is a good way to solve this.
我的想法是首先發出 API 請求來驗證令牌過期,該方法是在驗證和刷新完成后發出請求A、B、C.由于 cookie 是 HttpOnly,因此無法在客戶端 (JavaScript) 驗證到期日期.
My idea is to first make an API request to validate the token expiration, This method is to make requests A, B, and C after verification and refresh are completed. Because cookies are HttpOnly, the expiration date cannot be verified on the client side (JavaScript).
對不起,英語不好...
Sorry in poor english...
推薦答案
你需要做的是在攔截器之外維護一些狀態.說什么
What you'll need to do is maintain some state outside the interceptor. Something that says
等等,我正在獲取新令牌.
Hold up, I'm in the middle of getting a new token.
最好通過保留對 Promise
的引用來實現.這樣,第一個 401 攔截器可以創建 Promise,然后所有其他請求都可以等待它.
This is best done by keeping a reference to a Promise
. That way, the first 401 interceptor can create the promise, then all other requests can wait for it.
let refreshTokenPromise // this holds any in-progress token refresh requests
// I just moved this logic into its own function
const getRefreshToken = () => http.post('/token/refresh', {}, {
withCredentials: true,
headers: { 'X-CSRF-TOKEN': Vue.$cookies.get('csrf_refresh_token') }
}).then(() => Vue.$cookies.get('csrf_access_token'))
http.interceptors.response.use(r => r, error => {
if (error.config && error.response && error.response.status === 401) {
if (!refreshTokenPromise) { // check for an existing in-progress request
// if nothing is in-progress, start a new refresh token request
refreshTokenPromise = getRefreshToken().then(token => {
refreshTokenPromise = null // clear state
return token // resolve with the new token
})
}
return refreshTokenPromise.then(token => {
error.config.headers['X-CSRF-TOKEN'] = token
return http.request(error.config)
})
}
return Promise.reject(error)
})
這篇關于使用過期令牌發出同時 API 請求時如何避免多個令牌刷新請求的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!