请原谅我,如果这个问题完全脱离基础 - 我是JWT的新手。我有一个现有的单页应用程序,我已经转换到JWT而不是PHP会话。它的工作正常,但我想弄清楚如何刷新JWT(如有必要)在AJAX请求之前。一个小背景:在用户登录时,我存储了一个JWT(10分钟到期)和一个刷新令牌(2小时到期)。在每次AJAX调用API之前,我都想要运行以下函数。该函数检查JWT是否过期,如果是,则通过Refresh令牌检索新的JWT。显然,在API中,我会在允许数据被发回之前检查JWT和Refresh令牌的有效性。这部分工作完美。JWT刷新后运行AJAX Reqeust
function checkTokenExp(){
var validToken = false; // DEFAULT TO EXPIRED
var apiClaims = localStorage.getItem('apiToken').split('.');
var api = JSON.parse(atob(apiClaims[1]));
var apiExpiration = new Date(api['exp'] * 1000);
var now = new Date();
if (apiExpiration < now) {
// API TOKEN EXPIRED - CHECK REFRESH TOKEN
var refreshClaims = localStorage.getItem('refreshToken').split('.');
var refresh = JSON.parse(atob(refreshClaims[1]));
var refreshExpiration = new Date(refresh['exp'] * 1000);
if (refreshExpiration > now) {
// REFRESH TOKEN NOT EXPIRED - NEED NEW API TOKEN
$.ajax({
type: "GET",
url: 'api/session/token',
contentType: 'application/json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", 'Bearer '+localStorage.getItem('refreshToken'));
}
}).done(function (data) {
var data = jQuery.parseJSON(data);
if (data.status == 'success'){
localStorage.setItem('apiToken', data.apiToken);
}
validToken = true;
});
}else{
// REFRESH TOKEN EXPIRED - FORCE LOG OUT
$("#SessionExpiredModal").modal('show');
}
}else{
// API TOKEN NOT EXPIRED
validToken = true;
}
return validToken;
}
我遇到麻烦的地方在于下面的代码(以及其他所有的AJAX调用)。正如你所看到的,我试图在这个AJAX调用之前运行上面的函数并验证我的JWT(如果它的无效请求并存储了新的JWT),然后用新的JWT运行AJAX调用。除了AJAX返回401未经授权之外,它都可以工作,因为它仍在发送之前的JWT(显然已过期)。因此,似乎在上述功能完成之前发送AJAX并存储新的JWT。但是我知道我的函数运行正常,并且JWT已更新,因为第二次点击它正确运行的按钮,我得到了API的正确答复。
$('#BtnTest').on('click', function(){
$.ajax({
type: "GET",
url: 'api/random',
contentType: 'application/json',
beforeSend: function (xhr) {
checkTokenExp(); // SHOULD BE SAVING NEW TOKEN
xhr.setRequestHeader("Authorization", 'Bearer '+ localStorage.getItem('apiToken')); // SHOULD BE SENDING NEW TOKEN
}
}).done(function (response) {
alert(response);
})
});
我希望这是有道理的,并提前感谢您的帮助。另外,是否有一种简单的方法可以让我的函数在每个Ajax调用之前运行,而无需在每个AJAX语句中编写代码。
看一看那些: https://stackoverflow.com/questions/11793430/retry-a-jquery-ajax-request-which-has - 回调 - 附加到其推迟 https://stackoverflow.com/questions/21025552/refreshing-oauth2-tokens-in-async-js https://stackoverflow.com/questions/41118347/prevent -ajax-request-until-new-token-is-obtain/41118703 – pyb
感谢您的提示。它还没有工作。正如我所说,这对我来说有点新,而且我对ajaxPrefilter不熟悉。请告诉我,如果我对此的理解是正确的。 Prefilter在每个Ajax调用之前运行我的函数。 checkTokenExp()中的某处触发successCb()并允许ajax请求继续。那是对的吗。使用添加的Prefilter可以正常工作,直到令牌过期,然后它像以前一样失败。看起来好像第一个ajax调用在新的令牌保存之前仍然完成。 – bwlange3
我能够用你的一个建议链接中的代码解决这个问题 - [https://stackoverflow.com/questions/41118347/prevent-ajax-request-till-new-token-is-obtained/41118703](https ://stackoverflow.com/questions/41118347/prevent-ajax-request-till-new-token-is-obtained/41118703)。我的下一个问题是这个解决方案是否安全。如果访问令牌以某种方式更改,服务器将返回401,然后通过刷新令牌请求新令牌。这是需要关注的吗? – bwlange3