AngularJS应该如何处理由于过时的XSRF令牌而导致的$http.post 中的403错误



AngularJS 版本 1.4.8 应用程序在用户的浏览器保持打开状态多年(在本例中为 16 小时(后将数据发送到后端 REST 身份验证服务时,其登录表单将数据发送到后端 REST 身份验证服务时收到未处理的403错误。 经过更深入的分析,根本原因是客户端 AngularJS 应用程序具有过时的 XSRF-TOKENJSESSIONID cookie,这导致后端 Spring Security 拒绝对公共/login1服务的请求,因为 Spring 认为该请求是跨站点请求伪造的。

如果用户关闭所有浏览器窗口,然后在再次发出请求之前重新打开新的浏览器窗口,则可以手动解决此问题。 但这不是可接受的用户体验。 我已经阅读了此链接中的 AngularJS 文档,我看到我可以添加一个errorCallback函数,但是我应该如何具体重写该函数来处理403错误?

以下是授权服务中的原始this.logForm()方法,您可以看到它不处理403错误:

this.logForm = function(isValid) {
    if (isValid) {
        var usercredentials = {type:"resultmessage", name: this.credentials.username, encpwd: this.credentials.password };
        $http.post('/login1', usercredentials)
            .then(
                function(response, $cookies) {              
                    if(response.data.content=='login1success'){// do some stuff
                    } else {// do other stuff
                    }
                }
            );
    }
};

以下是我对 this.logForm() 方法的修订版的粗略尝试,尝试按照 AngularJS 文档中的示例处理403错误:

this.logForm = function(isValid) {
    if (isValid) {
        var usercredentials = {type:"resultmessage", name: this.credentials.username, encpwd: this.credentials.password };
        $http({ method: 'POST', url: '/login1', usercredentials })
            .then(
                function successCallback(response, $cookies) {
                    // this callback will be called asynchronously when the response is available
                    if(response.data.content=='login1success'){// do some stuff
                    } else {// do other stuff
                    }
                }, 
                function errorCallback(response, status) {// is status a valid parameter to place here to get the error code?
                    // called asynchronously if an error occurs or server returns response with an error status.
                    if(status == 403){
                        this.clearCookies();
                        // try to call this POST method again, but how?  And how avoid infinite loop?
                    }
                }
            );
        }
    };

需要对上面的代码进行哪些具体更改来处理由于服务器感知的 XSRF-TOKEN 和 JSESSIONID 问题而导致的 403 错误? 在删除 cookie 不能解决 403 错误的情况下,如何在删除 cookie 后第二次调用该帖子而不会导致无限循环?

我也在研究全局的错误处理方法,但存在公共和安全后端 REST 服务的组合,需要单独处理,从而导致复杂性。 此登录表单是用户输入的第一个点,我想在查看全局方法之前单独处理它,这些方法将使用为回复此 OP 而开发的方法保留对登录表单的单独处理。

你可以重组你的http调用以自动重试,并在你的控制器中使用承诺(或其他什么(

  var httpPostRetry = function(url, usercredentials) {
    var promise = new Promise(function(resolve, reject) {
    var retries = 0;
    var postRetry = function(url, usercredentials) {
      if (retries < 3) {
       $http({ method: 'POST', url: '/login1', usercredentials })
        .then(function(result) {
          resolve(result);
        }).catch(function(result) {
          retries ++;
          postRetry(url, usercredentials);
        });
      } else {
        reject(result);
      }
    };
  }.bind(this));
  return promise;
}

然后你会打电话

httpPostRetry(bla, bla).then(function(result) {
  // one of the 3 tries must of succeeded
}).catch(function(result) {
  // tried 3 times and failed each time
});

要处理特定的 http 错误,您可以广播该特定错误并在特定控制器中处理这种情况。或者使用服务封装状态,并让代码的其他部分处理该错误的 UI 流。

$rootScope.$broadcast('unauthorized http error', { somedata: {} });

这有帮助吗?

看看 angular-http-auth 模块以及那里是如何完成的。我认为您想要使用的一个关键元素是 http 拦截器。

用于全局错误处理、身份验证或任何类型的请求的同步或异步预处理或响应的后处理,希望能够拦截请求在传递给服务器之前,在之前响应它们被移交给启动这些内容的应用程序代码请求。拦截器利用承诺 API 来实现这一点需要同步和异步预处理。

在使用拦截器之后,您可以查看angular-http-auth http缓冲区以及它们在那里处理被拒绝请求的方式。如果他们的拦截器收到一个responseError,他们将config对象(基本上存储有关您的请求的所有信息(添加到缓冲区中,然后他们可以随时操作该缓冲区中的元素。当您收到 403 时,您可以轻松地熟练地使用他们的代码来代表您操作配置的 xsrfHeaderName、xsrfCookieName 或参数。

相关内容

最新更新