2013-04-09 31 views
6

在我的應用程序當用戶登錄時,我有authService其中設置內部標誌isAuthenticated。現在,在每一次路線變化中,我都會收聽$routeChangeStart事件,該事件會檢查authService.isAuthenticated()。如果不是,它應該重定向到登錄路由。AngularJS - 防止未經身份驗證的用戶訪問給定的路線

問題出在用戶刷新頁面(所有authService設置都丟失)並重新登錄(同時仍然在服務器上有效會話)。這不是我想要的。

我想什麼做的是「堵」的路線改變,直到我得到的信息,如果用戶通過驗證(從authService這將是直接的,或者從服務器,如果沒有信息是可用authService,如刷新後)。我在authService

 // returns promise 
     currentUser: function() { 
      if (authService.isAuthenticated()) { 
       return $q.when(authService.loggedUser); 
      } 
      return $http.get('/session').then(function(response) { 
       authService.loggedUser = response.user; 
       return $q.when(authService.loggedUser); 
      }); 
     } 

這樣的功能,並希望在事件偵聽器來使用它。

$rootScope.$on("$routeChangeStart", function (event, next, current) { 
     if(isRouteRestricted(next)) { 
      authService.currentUser().then(null, function() { 
       $location.path('/login'); 
      }); 
     } 
    }); 

問題是它不能按預期工作。我仍然可以在很短的時間內看到目標路由,然後用戶重定向。我相信這是由於承諾的性質,但如何擺脫這種「眨眼」效應?

回答

6

我會做這樣的事情在頂級控制器,這將是在頁面刷新時才能被稱爲第一控制器(用於在JS錯別字道歉,我是一個CoffeeScript的傢伙):

var authCheck = function (event, next, current) { 
    if(isRouteRestricted(next)) { 
     authService.currentUser().then(null, function() { 
      $location.path('/login'); 
     }); 
    } 
} 

authCheck(null, populateNextSomehow).then(function() { 
    // all of your controller code, probably in a separate function 
}); 

$rootScope.$on("$routeChangeStart", authCheck); 

這將確保在authCheck完成之前不能調用控制器代碼。

4

要防止用戶訪問你所要做的幾件事情路線:

首先,設置你的路由,並添加像「訪問」屬性:使用AllowAnonymous:true或false

// in app.js 
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);  
myApp.config(function ($httpProvider, $routeProvider) { 
    window.routes = { 
     '/Login': 
      { templateUrl: '/Account/Login', 
      controller: 'AccountController', 
      access : {allowAnonymous : true} 
      }, 
     '/MembersPage': 
      { templateUrl: '/Home/SomePage, 
      controller: SomePageController', 
      access: {allowAnonymous:false} 
      } 
     }; 

     for (var path in window.routes) { 
      $routeProvider.when(path, window.routes[path]); 
    } 
    $routeProvider.otherwise({ redirectTo: '/Login' }); 
}); 

其次,你必須認識到一個認證的用戶:

有幾種方法可以做到這一點,但我更喜歡在使用'服務'時使用AngularJS的強大功能。因此,我創建了一個'UserService',用於存儲當前用戶名和一個值 - 指示是否通過身份驗證。

// in UserService.js 
myApp.factory('userService', function() { 
var user = { 
    isLogged: false, 
    username: '',  
}; 

var reset = function() { 
    user.isLogged = false; 
    user.username = ''; 
}; 

return { 
    user: user, 
    reset : reset 
    }; 
}); 

最後一件事,捕捉路由變化事件,並相應地對待他們:

我們在的地方服務後,現在是時候使用它和實施路徑的檢查功能。有幾種攔截路由更改事件的方法,但我們只對那些在用戶重定向之前發生的方法感興趣,因此我們可以檢查是否經過身份驗證:'$ routeChangeStart','$ locationChangeStart'。在這裏,我們可以檢查用戶將要訪問的路由是否允許匿名訪問以及用戶是否登錄。如果發生故障,我們可以顯示錯誤消息並將用戶重定向到登錄頁面。

// in RootController.js 
myApp.controller('RootController', 
function ($scope, $route, $routeParams, $location, $rootScope, authenticationService, 
userService, toaster) { 
$scope.user = userService.user; 
$scope.$on('$routeChangeStart', function (e, next, current) {    
    if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) { 
       $location.path("/Login");     
      } 
     }); 

     $scope.logout = function() { 
      authenticationService.logout() 
       .success(function (response) { 
        userService.reset();      
        toaster.pop("info", 'You are logged out.', ''); 
       }); 
     }; 

$rootScope.$on("$locationChangeStart", function (event, next, current) { 
    for (var i in window.routes) { 
    if (next.indexOf(i) != -1) { 
    if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) { 
      toaster.pop("error", 'You are not logged in!', ''); 
      $location.path("/Login");             
        } 
       } 
      } 
     }); 
    }); 

完整的文章是在這裏:http://net-daylight.blogspot.ro/

希望它能幫助!

+1

請嘗試閱讀本文http://stackoverflow.com/help/deleted-answers,以獲得更多瞭解如何**不**回答。即:「不能從根本上回答問題的答案」:**僅僅是一個鏈接到外部網站** – 2013-12-02 12:44:11

相關問題