【问题标题】:Capture HTTP 401 with Angular.js interceptor使用 Angular.js 拦截器捕获 HTTP 401
【发布时间】:2014-02-09 09:52:15
【问题描述】:

我想使用 Angular.js 在单页 Web 应用程序上实现身份验证。 official Angular documentation 推荐使用拦截器:

$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
  return {

    // ...

    'responseError': function(rejection) {
      // do something on error
      if (canRecover(rejection)) {
        return responseOrNewPromise
      }
      return $q.reject(rejection);
    }
  };
});

问题是当服务器发送 401 错误时,浏览器立即停止并显示“未经授权”消息,或者登录弹出窗口(当服务器发送身份验证 HTTP 标头时),但 Angular 无法捕获它的按照建议拦截要处理的 HTTP 错误。我是不是误会了什么?我尝试了更多在网络上找到的示例(例如thisthisthis),但没有一个有效。

【问题讨论】:

  • 你有没有想过这个问题?我遇到了完全相同的问题
  • 这里一样,答案都不起作用,拦截器确实起作用,但异常仍然在拦截器之前抛出。这很奇怪吗?
  • 我已经尝试了很多东西,我仍然无法捕捉到 401。你在哪里可以只用一个拦截器来做到这一点? (由于某种原因,它被翻译成 404)@​​windmaomao

标签: angularjs authentication


【解决方案1】:

对于 AngularJS >1.3 使用 $httpProvider.interceptors.push('myHttpInterceptor');

.service('authInterceptor', function($q) {
    var service = this;

    service.responseError = function(response) {
        if (response.status == 401){
            window.location = "/login";
        }
        return $q.reject(response);
    };
})
.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
}])

【讨论】:

  • 'responseError' 是要做的事情。为了更好地衡量,请注意还有“requestError”。
  • 精彩的答案!它是一种通用功能,一旦您未经授权,它将重定向到登录。
  • 终于成功了!!!我最初使用的是“response”而不是“responseError”,这导致我的拦截器功能无法执行。
【解决方案2】:

在应用配置块中:

var interceptor = ['$rootScope', '$q', "Base64", function(scope, $q, Base64) {
  function success(response) {
    return response;
  }

  function error(response) {
    var status = response.status;
    if (status == 401) {
      //AuthFactory.clearUser();
      window.location = "/account/login?redirectUrl=" + Base64.encode(document.URL);
      return;
    }
    // otherwise
    return $q.reject(response);
  }
  return function(promise) {
    return promise.then(success, error);
  }
}];

【讨论】:

【解决方案3】:

我不知道为什么,但是 401 错误的响应进入了成功函数。

'responseError': function(rejection)
                {
                    // do something on error

                    if (rejection.status == 401)
                    {
                        $rootScope.signOut();
                    }

                    return $q.reject(rejection);
                },
                'response': function (response) {
                    // do something on error
                    if (response.status == 401) {
                        $rootScope.signOut();
                    };
                    return response || $q.when(response);
                }

【讨论】:

  • 'responseError' 很有帮助 :-)
  • 我还发现 401 以 response 而不是 responseError 结尾。角 1.5.3。编辑:看起来这可能是由于我正在使用的第 3 方库,http-auth-interceptor。即使我已指定该库应忽略此特定请求,它似乎仍然导致 401 无法通过 responseError 进行管道传输。
【解决方案4】:

AngularJS 拦截器仅适用于使用 $http 服务进行的调用;如果您导航到返回 401 的页面,AngularJS 甚至永远不会运行。

【讨论】:

  • 这取决于你所说的导航。页面(window.location)的完整加载确实不会触发拦截器。但是导航到应用程序中的另一条路线会,因为路线模板是使用 $http 服务获取的。
  • 在这种情况下你可以使用: .$on("$locationChangeStart", function (event, next, current) { 和 .$on("$locationChangeSuccess", function (event, next, current ) {
  • 如果你向服务器发起 $http 请求并返回 401,Angular 与它无关,应该由开发者决定怎么做;在这个问题的情况下,他可能希望将用户重定向到新路由,甚至可能删除双方的身份验证令牌。
猜你喜欢
  • 2023-03-17
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多