2014-01-20 11 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エラーをキャプチャすることはできません。私は何かを誤解していますか?私はもっ​​と多くの例をウェブ上で見つけようとしましたが(例えば、thisthisおよびthis)、それらのどれも働いていませんでした。アプリのconfigブロックで

+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

例: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

私は401sが 'responseError'ではなく' response'で終わるのを発見しました。角度1.5.3。編集:それは 'http-auth-interceptor'を使用しているサードパーティ製のlibのためかもしれないようです。この特定の要求をそのlibで無視するように指定したとしても、それはまだ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

関連する問題