Javascript 在JWT刷新后运行AJAX请求
我有一个现有的单页应用程序,我已经将其转换为JWT而不是PHP会话。它工作得很好,但我正在试图弄清楚如何在AJAX请求之前刷新JWT(如果必要的话) 一点背景:在用户登录时,我存储一个JWT(10分钟到期)和一个刷新令牌(2小时到期)。我想在每次调用API之前运行以下函数。该函数检查JWT是否过期,如果过期,则通过刷新令牌检索新的JWT。显然,在API中,我在允许返回数据之前检查JWT和刷新令牌的有效性。这部分工作得很好Javascript 在JWT刷新后运行AJAX请求,javascript,jquery,ajax,token,jwt,Javascript,Jquery,Ajax,Token,Jwt,我有一个现有的单页应用程序,我已经将其转换为JWT而不是PHP会话。它工作得很好,但我正在试图弄清楚如何在AJAX请求之前刷新JWT(如果必要的话) 一点背景:在用户登录时,我存储一个JWT(10分钟到期)和一个刷新令牌(2小时到期)。我想在每次调用API之前运行以下函数。该函数检查JWT是否过期,如果过期,则通过刷新令牌检索新的JWT。显然,在API中,我在允许返回数据之前检查JWT和刷新令牌的有效性。这部分工作得很好 function checkTokenExp(){ va
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语句中对其进行编码。您需要向
checkTokenExp()
添加回调,以便在刷新API令牌后完成API调用
现在发生了什么:
api/random
beforeSend
执行checkTokenExp()
api/random
,可能是在服务器使用新令牌响应第三步之前var currentRequests={};
$.ajaxPrefilter(函数(选项、原始选项、jqXHR){
//跳过不需要令牌的URL
如果(options.url==“您的api/会话/令牌url”){
log(“api/session/token上没有ajax预过滤器”);
返回;
}
successCb=函数(){
currentRequests[options.url]=jqXHR;
};
errorCb=函数(){
错误(“无法刷新令牌,中止对“+options.url”的Ajax调用);
currentRequests[options.url]。中止();
};
checkTokenExp(successCb,errorCb);
});
函数checkTokenExp(successCb,errorCb){
// ...
如果(刷新过期>现在){
//刷新令牌未过期-需要新的API令牌
$.ajax({
键入:“获取”,
url:'api/session/token',
contentType:'应用程序/json',
}).完成(功能(数据){
var data=jQuery.parseJSON(数据);
如果(data.status==“成功”){
localStorage.setItem('apiToken',data.apiToken);
successCb();//设置新令牌后,可以进行ajax调用
}
//TODO:此处记录错误,不执行validToken=true
}).失败(错误CB(数据));
}否则{
//刷新令牌已过期-强制注销
$(“#SessionExpiredModal”).modal('show');
}
}否则{
//API令牌未过期
successCb();
}
}
您需要向checkTokenExp()
添加回调,以便在刷新API令牌后完成API调用
现在发生了什么:
api/random
beforeSend
执行checkTokenExp()
api/random
,可能是在服务器使用新令牌响应第三步之前var currentRequests={};
$.ajaxPrefilter(函数(选项、原始选项、jqXHR){
//跳过不需要令牌的URL
如果(options.url==“您的api/会话/令牌url”){
log(“api/session/token上没有ajax预过滤器”);
返回;
}
successCb=函数(){
currentRequests[options.url]=jqXHR;
};
errorCb=函数(){
错误(“无法刷新令牌,中止对“+options.url”的Ajax调用);
currentRequests[options.url]。中止();
};
checkTokenExp(successCb,errorCb);
});
函数checkTokenExp(successCb,errorCb){
// ...
如果(刷新过期>现在){
//刷新令牌未过期-需要新的API令牌
$.ajax({
键入:“获取”,
url:'api/session/token',
contentType:'应用程序/json',
}).完成(功能(数据){
var data=jQuery.parseJSON(数据);
如果(data.status==“成功”){
localStorage.setItem('apiToken',data.apiToken);
successCb();//设置新令牌后,可以进行ajax调用
}
//TODO:此处记录错误,不执行validToken=true
}).失败(错误CB(数据));
}否则{
//刷新令牌已过期-强制注销
$(“#SessionExpiredModal”).modal('show');
}
}否则{
//API令牌未过期
successCb();
}
}
看看这些:谢谢你的提示。它还没有完全起作用。正如我所说,这对我来说有些陌生,我对ajaxPrefilter并不熟悉。请告诉我我对这一点的理解是否正确。预过滤器在每次ajax调用之前运行my函数。它在checkTokenExp()中的某个地方激发successCb(),并允许ajax请求继续。对吗。它可以使用添加的预过滤器正常工作,直到令牌过期,然后像以前一样失败。在保存新令牌之前,第一个ajax调用似乎仍在完成。我的下一个问题是这个解决方案安全吗。如果访问令牌以某种方式被更改,服务器将返回401,然后通过刷新令牌请求新令牌。这是值得关注的吗?bug:我没有完整的代码,因此很难进一步提供帮助。如果还没有,请学习如何使用开发人员工具和浏览器的JavaScript调试。你会看到发生了什么。问题:请将您的问题标记为已回答,以便社区知道您不需要
$('#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);
})
});