web-dev-qa-db-ja.com

AngularJS |ロードする前にルーティングを処理する

外部サービスによるルートの簡単な認証チェックを作成したいと思います。

ルートオブジェクトのアクセス要件を定義します。

$routeProvider
    .when('/', {
        templateUrl: 'src/app/views/index.html',
        controller: 'indexCtrl',
        authenticated: true
    })
    .when('/login', {
        templateUrl: 'src/app/views/login.html',
        controller: 'loginCtrl',
        anonymous:  true
    })
    .otherwise({
        redirectTo: '/'
    })
;

次に、$routeChangeStartイベント内で権限を持っているかどうかを確認します。

$rootScope.$on('$routeChangeStart', function (event, next) {
    if(next.authenticated && !$myService.isLoggedin())
        $location.path("/login");
    else if(next.anonymous && $myService.isLoggedin())
        $location.path("/secured");
});

実際に、それは動作します-
認証されていないユーザーがログインページに移動した場合、認証されていてもルートが匿名ユーザーのみの場合、ユーザーを別のページに移動するなど。

ただし、このリダイレクトは実際にコントローラーとテンプレートがロードされた後に発生します!そして、コントローラーは、私のREST API、 m認証されていません。

処理する前にどのようにルートを処理できますか?

17
Almog Baku

私の解決策は$locationChangeStart$routeChangeStartを組み合わせることでした:

$rootScope.$on('$locationChangeStart', function (event) {
    //If login data not available, make sure we request for it
    if($facebook.isConnected()==null) {
        $facebook.getLoginStatus();
        event.preventDefault();
        return;
    }

    var next=parseRoute().$$route;
    if(!Auth.loginCheck(next))
        event.preventDefault();
});

parseRoute()angular-route.jsからコピーして、指定されたURLを解析してルーティングしました。

次に、ログインチェックハンドラー(Auth.loginCheck)を作成し、失敗するとfalseを返すようにします。

また、$routeChangeStartを使用して$route.reload()イベントを処理するため、認証ステータス内のすべての変更後に$route.reload()を実行します。

$rootScope.$on('$routeChangeStart', function (event, next) {
    Auth.loginCheck(next);
});

最後に、単純なrun()メソッドを使用して、このカスタムサービスが常に実行されることを確認します。

編集:

私たちは今、その正確な問題を解決するために設計したモジュールであるngAuthを使用しています(以前にここで与えた答えに基づいて)。

最後に、この問題を解決する角度モジュールを開発しました。このモジュールは、以前にここで公開した回答に基づいています。

ここでのリクエストにより、現在動作するベータリリースを公開しました。 http://github.com/GoDisco/ngAuth

気軽に使用してください。

16
Almog Baku

$ routeProvider resolve を使用します

.when('/', {
    templateUrl: 'src/app/views/index.html',
    controller: 'indexCtrl',
    resolve: function($q, $location) {
      var deferred = $q.defer(); 
      deferred.resolve();
      if (!isAuthenticated) {
         $location.path('/login');
      }

      return deferred.promise;
    }
})
23
codef0rmer

ルートのresolveプロパティを使用してみてください。コントローラまたはテンプレートがロードされる前に、渡されたすべての機能/依存関係を解決します。依存関係がプロミスを返す場合、解決されたものは何もロードされません。

解決に認証サービスを渡し、認証エラーの場合にリダイレクトしてください。

ご覧ください-> https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw

$ stateProviderは、下で$ routeProviderを使用します。このwikiはより多くの洞察を与えてくれます。 https://github.com/angular-ui/ui-router/wiki#resolve

1

Angularjsの解決例:

.when('/profile', {
        templateUrl: 'views/profile.html',
        controller: 'ProfileCtrl',
        resolve: {
            app: function($q, $rootScope, $location) {
                var defer = $q.defer();
                if ($rootScope.currentUser == undefined) {
                    $location.path('/login');
                };
                defer.resolve();
                return defer.promise;
            }
        }
1
lsampaio

Angular-http-authを使用すると、HTTPレベル(テンプレートの取得時)で非常にエレガントな承認を処理し、必要に応じてログインを要求できます。許可が拒否された場合、テンプレート(コントローラーも)をロードすることなく、すべてのこと。明らかにこれまで見た中で最高のもの。

https://github.com/witoldsz/angular-http-auth

0
PowerKiKi