2014-01-20 167 views
41

我想通過Angular.js在單個頁面的web應用上實現身份驗證。該official Angular documentation建議使用攔截器:使用Angular.js攔截器捕獲HTTP 401

$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錯誤處理,如推薦。我誤解了什麼嗎?我嘗試了更多在網上找到的例子(例如this,thisthis),但他們都沒有工作。

+0

你有沒有得到這個想通了?我有完全相同的問題 –

+0

凹凸不平,在這裏! – Romain

+0

同樣在這裏,答案都沒有用,攔截器確實有效,但異常仍然在攔截器之前拋出。這是不是很奇怪? – windmaomao

回答

24

在應用程序配置塊:

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); 
    } 
}]; 
+0

實施例(出於某種原因,它被轉換爲一個404):https://github.com/stefchri/Radar/blob/master/Radar/RadarAPI/Radar/app/js/app.js –

+3

responseInterceptor不再在1.3中支持 – natdico

+8

在1.3中綁定如下:$ httpProvider.interceptors.push('interceptor'); –

8

我不知道爲什麼,但響應與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); 
       } 
+1

'responseError'對我非常有幫助:-) – joy

+1

我也發現401以'response'而不是'responseError'結尾。角1.5.3。編輯:看起來像它可能是由於我使用的第三方庫,'http-auth-interceptor'。即使我已經指定這個特定的請求應該被該庫忽略,但它似乎仍然導致401不通過'responseError'。 – elwyn

7

AngularJS攔截器僅適用於使用$ http服務進行的調用;如果您導航到返回401的頁面,AngularJS甚至不會運行。

+3

這取決於你所謂的導航。一個頁面的完整加載(window.location)確實不會觸發攔截器。但導航到應用程序中的另一個路線將會因爲使用$ http服務獲取路線模板。 –

+0

在這種情況下,你可以使用: $上( 「$ locationChangeStart」 功能(事件,接下來,電流){ 而 $上( 「$ locationChangeSuccess」 功能(事件,接下來,電流){。 – Chen

+0

如果您向服務器發出$ http請求並返回401,則Angular與此無關,開發人員應決定如何處理;在此問題中,他可能希望將用戶重定向到新路由或甚至可能刪除雙方的認證令牌 – M98

53

對於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'); 
}]) 
+1

'responseError'是要做的事情,對於好的措施,請注意,也有'requestError'。 – eflat

+0

精彩的答案!它的一個通用功能,一旦你擅自將它重定向到登錄。 – sebu