Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在JWT刷新后运行AJAX请求_Javascript_Jquery_Ajax_Token_Jwt - Fatal编程技术网

Javascript 在JWT刷新后运行AJAX请求

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

我有一个现有的单页应用程序,我已经将其转换为JWT而不是PHP会话。它工作得很好,但我正在试图弄清楚如何在AJAX请求之前刷新JWT(如果必要的话)

一点背景:在用户登录时,我存储一个JWT(10分钟到期)和一个刷新令牌(2小时到期)。我想在每次调用API之前运行以下函数。该函数检查JWT是否过期,如果过期,则通过刷新令牌检索新的JWT。显然,在API中,我在允许返回数据之前检查JWT和刷新令牌的有效性。这部分工作得很好

    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);
        })
       });