Dmi*_*dov 35 javascript authentication ajax promise axios
我正在我的网络应用程序中实现令牌身份验证.我的access token
每N分钟过期,而不是refresh token
用于登录并获得新的access token
.
我使用Axios进行所有API调用.我有拦截器设置来拦截401
响应.
axios.interceptors.response.use(undefined, function (err) {
if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
serviceRefreshLogin(
getRefreshToken(),
success => { setTokens(success.access_token, success.refresh_token) },
error => { console.log('Refresh login error: ', error) }
)
err.config.__isRetryRequest = true
err.config.headers.Authorization = 'Bearer ' + getAccessToken()
return axios(err.config);
}
throw err
})
Run Code Online (Sandbox Code Playgroud)
基本上,当我拦截401响应时,我想进行登录,然后使用新令牌重试原始被拒绝的请求.我的serviceRefreshLogin
函数调用setAccessToken()
它的then
块.但问题是then
阻塞发生的时间晚于getAccessToken()
拦截器,因此重试发生在旧的过期凭证上.
getAccessToken()
并getRefreshToken()
简单地返回存储在浏览器中的现有标记(它们管理localStorage,cookies等).
在承诺返回之前,我将如何确保语句不会执行?
(这是github上的相应问题:https://github.com/mzabriskie/axios/issues/266)
For*_*ser 25
只是使用另一个承诺:D
axios.interceptors.response.use(undefined, function (err) {
return new Promise(function (resolve, reject) {
if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
serviceRefreshLogin(
getRefreshToken(),
success => {
setTokens(success.access_token, success.refresh_token)
err.config.__isRetryRequest = true
err.config.headers.Authorization = 'Bearer ' + getAccessToken();
axios(err.config).then(resolve, reject);
},
error => {
console.log('Refresh login error: ', error);
reject(error);
}
);
}
throw err;
});
});
Run Code Online (Sandbox Code Playgroud)
如果您的环境不支持承诺使用polyfill,例如https://github.com/stefanpenner/es6-promise
但是,重写getRefreshToken以返回promise然后使代码更简单可能更好
axios.interceptors.response.use(undefined, function (err) {
if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
return getRefreshToken()
.then(function (success) {
setTokens(success.access_token, success.refresh_token) ;
err.config.__isRetryRequest = true;
err.config.headers.Authorization = 'Bearer ' + getAccessToken();
return axios(err.config);
})
.catch(function (error) {
console.log('Refresh login error: ', error);
throw error;
});
}
throw err;
});
Run Code Online (Sandbox Code Playgroud)
演示https://plnkr.co/edit/0ZLpc8jgKI18w4c0f905?p=preview
可以在请求中而不是在响应中执行此操作,它可能会更干净,因为它可以避免在访问令牌过期时访问服务器。从本文复制:
function issueToken() {
return new Promise((resolve, reject) => {
return client({
...
}).then((response) => {
resolve(response);
}).catch((err) => {
reject(err);
});
});
}
client.interceptors.request.use((config) => {
let originalRequest = config;
if (tokenIsExpired && path_is_not_login) {
return issueToken().then((token) => {
originalRequest['Authorization'] = 'Bearer ' + token;
return Promise.resolve(originalRequest);
});
}
return config;
}, (err) => {
return Promise.reject(err);
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
35378 次 |
最近记录: |