6

在我的应用程序中,当用户登录时,我authService设置了 internal flag isAuthenticated。现在,在每次路由更改时,我都会将侦听器附加到$routeChangeStart检查authService.isAuthenticated(). 如果没有,它应该重定向到登录路由。

问题是当用户刷新页面(所有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');
            });
        }
    });

问题是它没有按预期工作。我仍然可以在很短的时间内看到目标路线,然后用户被重定向。我相信这是由于承诺的性质,但如何摆脱这种“眨眼”效应?

4

2 回答 2

6

我会在顶级控制器中执行类似的操作,这将是刷新页面时调用的第一个控制器(为 js 中的拼写错误道歉,我是咖啡师):

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 完成之前无法调用控制器代码。

于 2013-04-09T15:44:17.823 回答
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/

希望能帮助到你!

于 2013-12-02T12:27:17.923 回答