AngularJS 中的 401 未经授权的错误处理
Posted
技术标签:
【中文标题】AngularJS 中的 401 未经授权的错误处理【英文标题】:401 unauthorized error handling in AngularJS 【发布时间】:2013-09-11 03:24:42 【问题描述】:我是 AngularJS 的新手,现在花了 3 天时间寻找处理 401 状态的方法。我试过拦截器,使用 $http,使用 $resource ......但没有任何效果。我的应用程序在同一台服务器上调用 JSONP 调用。当错误发生时,它会被错误回调函数捕获。但状态始终为 0,响应未定义。
首先,我尝试了这个拦截器
app.config(['$httpProvider', function($httpProvider)
$httpProvider.responseInterceptors.push(['$q', function($q)
return function(promise)
return promise.then(function(response)
console.log('success in interceptor');
return response;
, function(response)
console.log('error in interceptor');
console.log(response);
if (response.status === 401)
response.data =
status: false,
description: 'Authentication required!'
;
return response;
return $q.reject(response);
);
]);
]);
其次,也在使用 $resource 的控制器中尝试过
$scope.fetchData = function(fromDate, toDate)
Cancel.get(from: fromDate, to: toDate, perPage: 99999,
function(data)
$scope.cancels = $scope.filteredCancels = data.data;
$scope.search();
,
function(response)
$scope.errorMessage = '<h4>Error : '+response.status+'</h4>';
window.location = "/";
);
;
第三,尝试使用$http而不是$resource
$scope.fetchData = function(fromDate, toDate)
$http.jsonp('http://host:8900/api/cancellations?callback=JSON_CALLBACK')
.success(function(data, status, headers, config)
console.log(status);
)
.error(function(data, status, headers, config)
console.log(status);
;
这是 JSONP 调用的标头信息
Request URL:http://host:8900/api/cancellations?callback=angular.callbacks._0
Request Method:GET
Status Code:401 Unauthorized
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Cookie:__utma=149207145.339724205.1374885003.1377550245.1378313049.3; __utmc=149207145; __utmz=149207145.1378313049.3.2.utmcsr=cyphersmart.qc3deva.electricmail.com:8900|utmccn=(referral)|utmcmd=referral|utmcct=/; remember_username=elie.kim%40electricmail.com; phpSESSID=gdoemlp5jltqq62etc5gfuh653; cookie=cookiecheck; __utma=1.789184132.1378340585.1378499390.1378504453.10; __utmb=1.3.10.1378504453; __utmc=1; __utmz=1.1378340585.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:host:8900
Referer:http://host:8900/reports/cancels/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (Khtml, like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22
Query String Parametersview sourceview URL encoded
callback:angular.callbacks._0
Response Headersview source
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Type:application/json; charset=utf-8
Date:Fri, 06 Sep 2013 22:02:13 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive:timeout=20
Pragma:no-cache
Server:nginx/0.7.65
Transfer-Encoding:chunked
我找不到处理未授权状态 401 的方法,但我把所有东西都绑定了。如果我能得到小费或善意的建议,将不胜感激。
【问题讨论】:
如果您在浏览器中导航到您的 URL,会发生什么? 您使用的是什么版本的 Angular?这很重要,因为responseInterceptors
在 1.2 中发生了变化
@TheSharpieOne 我的版本是 v1.0.6。是这个原因吗?
@akonsu 它会捕获除 200 或 300 之外的任何 ajax 错误。我很痛苦的是为什么它无法捕获 401 状态代码。
找到了AngularJs没有捕获401状态的原因,它不应该在调用JSONP请求时捕获401。只要将方法更改为“GET”,它就会很好地捕捉到。
【参考方案1】:
接受的答案不适用于更高版本的 Angular。使用 1.5.x(甚至更早),您需要以不同的方式编写拦截器:
// http interceptor to handle redirection to login on 401 response from API
app.factory('httpResponseInterceptor', ['$q', '$rootScope', '$location', function($q, $rootScope, $location)
return
responseError: function(rejection)
if (rejection.status === 401)
// Something like below:
$location.path('signin/invalidSession');
return $q.reject(rejection);
;
]);
申请:
app.config(function($httpProvider)
$httpProvider.interceptors.push('httpResponseInterceptor');
);
更多信息请参见此处https://docs.angularjs.org/api/ng/service/$http#interceptors
【讨论】:
【参考方案2】:我最近需要做类似的事情,这是我的拦截器
app.factory("HttpErrorInterceptorModule", ["$q", "$rootScope", "$location",
function($q, $rootScope, $location)
var success = function(response)
// pass through
return response;
,
error = function(response)
if(response.status === 401)
// dostuff
return $q.reject(response);
;
return function(httpPromise)
return httpPromise.then(success, error);
;
]).config(["$httpProvider",
function($httpProvider)
$httpProvider.responseInterceptors.push("HttpErrorInterceptorModule");
]);
为您的用例稍作修改
【讨论】:
【参考方案3】:如果任何 API 调用返回 401,我们必须将用户重定向到登录页面。 Angular 的 HTTP 拦截器非常适合这项工作。从上面的 app.js 可以看出,它被推送到了这里:
httpProvider.responseInterceptors.push('httpInterceptor');
拦截器实现本身,
'use strict';
angular.module('dashboardApp').factory('httpInterceptor', function httpInterceptor ($q, $window, $location)
return function (promise)
var success = function (response)
return response;
;
var error = function (response)
if (response.status === 401)
$location.url('/login');
return $q.reject(response);
;
return promise.then(success, error);
;
);
【讨论】:
在重定向到 location.path(/login) 时如何向用户显示他退出的原因?【参考方案4】:遵循类似的解决方案...
angular.module('myApp', ['myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider, $location)
var httpInterceptor = ['$rootScope', '$q', function (scope, $q)
function success(response)
return response;
function error(response)
var status = response.status;
if (status == 401)
$location.url('/login');
return;
return $q.reject(response);
return function (promise)
return promise.then(success, error);
];
$httpProvider.responseInterceptors.push(httpInterceptor);
);
【讨论】:
$httpProvider.interceptors.push("HttpErrorInterceptorModule");以上是关于AngularJS 中的 401 未经授权的错误处理的主要内容,如果未能解决你的问题,请参考以下文章
如果刷新(JWT)令牌未经授权(401响应),AngularJS重定向到登录
在 grails 应用程序中调用 spring security rest 插件登录时出现 401 未经授权的错误
Spring Boot / Spring Security中的错误401未经授权