2013-11-04 64 views
1

我想在AngularJS中實現基本的認證路由。我有一個擁有返回承諾的授權方法的模型。我希望路由等待,直到授權函數返回true或false才能繼續,一旦完成,它應該恢復路徑或將用戶重定向到登錄頁面。AngularJS路由與授權過程

我認爲本質上我需要停止路由,調用該方法,然後恢復或重定向到登錄。以下是我目前爲止的代碼,但我不確定如何完成暫停/恢復。有任何想法嗎?

return angular.module('d', ['ngCookies', 'ngRoute']) 
    .config(['$routeProvider', '$locationProvider', '$httpProvider', 
     function ($routeProvider, $locationProvider, $httpProvider) { 

      $routeProvider.when('/', 
      { 
       templateUrl: 'views/home.html', 
       controller: 'HomeCtrl' 
      }); 
      $routeProvider.when('/login', 
      { 
       templateUrl: 'views/login.html', 
       controller: 'LoginCtrl' 
      }); 

      $routeProvider.otherwise({ redirectTo: '/404' }); 
      $locationProvider.html5Mode(true); 

      // handle unauthorized requests by redirecting to login page 
      $httpProvider.responseInterceptors.push(
       ['$location', '$q', function ($location, $q) { 
        function success(response) { 
         return response; 
        } 

        function error(response) { 
         if (response.status === 401) { 
          $location.path('/login'); 
          return $q.reject(response); 
         } 
         else { 
          return $q.reject(response); 
         } 
        } 

        return function (promise) { 
         return promise.then(success, error); 
        } 
       }]); 

     }]) 
    .run(['$rootScope', '$location', 'Auth', function ($rootScope, $location, Auth) { 

     $rootScope.$on("$routeChangeStart", function (event, next, current) { 
      $rootScope.error = null; 
      Auth.authorize().then(function(){ 
       $location.path('/'); 
      },function(){ 
       $location.path('/login'); 
      }); 
     }); 

    }]); 
+0

[$ routeProvider resolve] [1]是我感覺的正確方法。 [1]:http://stackoverflow.com/questions/18788586/angularjs-handle-routing-before-they-load – amcdnl

+0

你能提供'authorize'方法請 – Merlin

回答

2

您的解決方案與我後面寫的原型非常相似。

這個想法是,無論何時你「觸摸」服務器並獲得認證錯誤,彈出一個模式窗口,要求登錄而不是更改URL(你可以讓它更改爲新的URL並留在那裏) 。

我的實現也是基於401的攔截器檢查。它依賴於$ rootScope並將屬性「needsLogin」設置爲true。當needsLogin === true並隱藏ng視圖時,頁面模板具有可見的登錄模式窗口(這一點很重要,因爲新的路由已經被加載,但是它未命中其數據)。最後,成功登錄後,登錄控制器執行$route.reload(),然後設置$rootScope.needsLogin = false

小片段:

<div id="main" role="main" ng-show="needsLogin === false"> 
    <div ng-view></div> 
</div> 

<div ng-show="needsLogin === true" ng-include="'views/login.html'" class="overlay"></div> 

登錄控制器可以是這樣的:

function LoginCtrl($scope, $rootScope, $route, $http) { 

    $scope.login = function() { 
     $http.post(/* Somehow do your login */) 
      .success(function() { 
       var deregister = $rootScope.$on('$routeChangeSuccess', function() { 
        // hide login/show ng-view after route has been reloaded 
        $rootScope.needsLogin = false; 
        deregister(); 
       }); 
       $route.reload(); 
      }) 
      .error(function() { 
       /* handle errors */ 
      }); 
    }; 
} 

$route.reload()不是一個完整的頁面刷新,它只是重新初始化路線(控制器/圖等) 。希望之前被拒絕的電話會再次運行,頁面將會正常工作。

+0

我喜歡你這個主意將模式放在頂部以更好地保留網址,在代碼中,我沒有在此示例中顯示我緩存了網址,然後在成功後重定向。我很害怕這種方法,我可能因爲通過服務認證失敗而得到那個對話框之前得到大量的錯誤。 – amcdnl

+0

我發現這個https://gist.github.com/thomasnordlund/4025773,但它似乎過於複雜。 – amcdnl