我想知道是否可以这样做,因为我不确定是否我错了或者不可能。基本上,我想要做的是创建一个本地fetch
JavaScript函数的包装功能。这个包装函数将实现令牌验证过程,如果给定的过期已过期并请求再次请求所需的资源,则请求新的accessToken
。这是我已经到了到现在为止:将javascript抓取以添加自定义功能
customFetch.js
// 'url' and 'options' parameters are used strictely as you would use them in fetch. 'authOptions' are used to configure the call to refresh the access token
window.customFetch = (url, options, authOptions) => {
const OPTIONS = {
url: '',
unauthorizedRedirect: '',
storage: window.sessionStorage,
tokenName: 'accessToken'
}
// Merge options passed by user with the default auth options
let opts = Object.assign({}, OPTIONS, authOptions);
// Try to update 'authorizarion's header in order to send always the proper one to the server
options.headers = options.headers || {};
options.headers['Authorization'] = `Bearer ${opts.storage.getItem(opts.tokenName)}`;
// Actual server request that user wants to do.
const request = window.fetch(url, options)
.then((d) => {
if (d.status === 401) {
// Unauthorized
console.log('not authorized');
return refreshAccesToken();
}
else {
return d.json();
}
});
// Auxiliar server call to get refresh the access token if it is expired. Here also check if the
// cookie has expired and if it has expired, then we should redirect to other page to login again in
// the application.
const refreshAccesToken =() => {
window.fetch(opts.url, {
method: 'get',
credentials: 'include'
}).then((d) => {
// For this example, we can omit this, we can suppose we always receive the access token
if (d.status === 401) {
// Unauthorized and the cookie used to validate and refresh the access token has expired. So we want to login in to the app again
window.location.href = opts.unauthorizedRedirect;
}
return d.json();
}).then((json) => {
const jwt = json.token;
if (jwt) {
// Store in the browser's storage (sessionStorage by default) the refreshed token, in order to use it on every request
opts.storage.setItem(opts.tokenName, jwt);
console.log('new acces token: ' + jwt);
// Re-send the original request when we have received the refreshed access token.
return window.customFetch(url, options, authOptions);
}
else {
console.log('no token has been sent');
return null;
}
});
}
return request;
}
consumer.js
const getResourcePrivate =() => {
const url = MAIN_URL + '/resource';
customFetch(url, {
method: 'get'
},{
url: AUTH_SERVER_TOKEN,
unauthorizedRedirect: AUTH_URI,
tokenName: TOKEN_NAME
}).then((json) => {
const resource = json ? json.resource : null;
if (resource) {
console.log(resource);
}
else {
console.log('No resource has been provided.');
}
});
}
我会尽力解释好一点上面的代码:我想使对用户透明令牌验证,以便让他们只是担心要求他们想要的资源。当accessToken
仍然有效时,此方法工作正常,因为return request
指令正在向消费者提供fetch
请求的承诺。
当然,当accessToken
已过期,我们要求一个新的auth
服务器,这是行不通的。令牌刷新并请求私人资源,但consumer.js
没有看到它。
对于这最后一种情况,是否可以修改程序的流程,以便刷新accessToken
并执行服务器调用以再次获取专用资源?消费者不应该意识到这个过程;在这两种情况下(accessToken
有效并且accessToken
已过期并且已被刷新)consumer.js
应该在其then
函数中获得私人请求的资源。
噢,我想我太晚了:DI想建议在这里删除一组括号'const refreshAccesToken =()=> window.fetch(...);'这样''refreshAccesToken''应该返回一个承诺,而不是'undefined',一切都应该工作正常 –
@丹尼斯你是对的!Y在这个功能上犯了一个错误,我忘了回复这个承诺。我已经尝试过,并且工作正常,所以我会编辑我的答案以便添加您的方法,这更接近我的初始解决方案。 – christiansr85