如何刷新jwt并重新发送失败的http请求

How to refresh jwt and resend failed http request?

本文关键字:新发送 失败 请求 http jwt 何刷新 刷新      更新时间:2023-09-26

我有一个带有jwt授权的后端,我想处理过期的令牌。

需要以下流程:

  1. 发出带有令牌的请求(并期望得到承诺)
  2. 如果运行正常,则返回promise(调用者的then/fail方法被执行)
  3. 如果失败(401未授权),则发出刷新令牌的请求,令牌在本地更新
  4. 如果步骤3成功,返回原始请求的承诺
  5. 如果步骤3使用401失败(令牌无法刷新),错误重定向到登录页面

问题:在步骤4中,原始函数被调用(再次),但是调用者的then/fail方法没有被触发。

下面是我的方法来附加jwt令牌到url并发送http请求:

var AuthenticatedRequest = function(url, data, method) {
  return (function tryRequest(){
    console.log('calling tryRequest');
    return reqwest({
        url: ApiUtil.tokenUrlTo(url),
        method: method,
        crossOrigin: true,
        type: 'json',
        data: data
      })
      .fail(function(err) {
        if (err.status === 401) {
          return post('/auth/refresh-token')
            .then(function(response){
              console.log('assume token set');
              //code to update token locally
            })
            .then(tryRequest)
            .fail(function(err){
              // Can't refresh token. Send to login page
            })
          ;      
        }
      })
    ;
  })();
};

来电者:

fetchModules: function() {
    get('/admin/modules')
      .then(function(response) {
        Actions.modulesFetchSuccess(response.collection);
      })
      .fail(function(err) {
        Actions.modulesFetchError(ApiUtil.errorArrayForResponse(err));
      })
    ;
  },

现在,如果我因为令牌过期而获得401,我触发一个新的周期来刷新令牌,如这个问题中所建议的,在失败后重新启动一个承诺。

注意:postget函数只是AuthenticatedRequest函数的包装,方法设置为POSTGET

AuthenticatedRequest函数返回一个承诺,如果令牌没有过期,则运行正常,然而,当令牌过期时,我在控制台中得到一个错误,并获取新的令牌,并再次调用该函数,我的控制台的屏幕截图- https://i.stack.imgur.com/hJdId.png

但是fetchModulesthen方法在令牌更新后不会被触发。我做错了什么?

可能的副本:

    AngularJS -处理刷新令牌?
  • 如何在未被授权时重新发送请求
  • 承诺失败后重新启动

2015年9月13日更新

@Bergi的答案工作时,我取代了reqwest.js和使用q.js香草ajax显示在这个要点

问题是.fail总是捕获您的错误,而不仅仅是第一次。对tryRequest的递归调用将包括重试本身,并且永远不会返回失败的承诺。
如果只需要一次重试,则需要将其放在外部:

function AuthenticatedRequest(url, data, method) {
  function tryRequest() {
    console.log('calling tryRequest');
    return reqwest({
      url: ApiUtil.tokenUrlTo(url),
      method: method,
      crossOrigin: true,
      type: 'json',
      data: data
    });
  }
  return tryRequest().fail(function(err) {
    if (err.status !== 401) throw err;
    return post('/auth/refresh-token')
    .then(function(response) {
      console.log('assume token set');
      // code to update token locally
    })
    .then(tryRequest)
    .fail(function(err) {
      // Can't refresh token. Send to login page
    });
  });
}

请注意,从AuthenticatedRequest函数将用户发送到另一个页面可能不是一个好的设计,也许可以考虑重新抛出错误(在令牌无效之后?),并将重定向和所有内容放在调用者的错误处理程序中。