一种解决方案是广播一个“notAuthorized”事件,并在主作用域中捕获它以重新更改位置。我认为这不是最好的解决方案,但它对我有用:
myApp.run(['$rootScope', 'LoginService',
    function ($rootScope, LoginService) {
        $rootScope.$on('$routeChangeStart', function (event, next, current) {
            var authorizedRoles = next.data ? next.data.authorizedRoles : null;
            if (LoginService.isAuthenticated()) {
                if (!LoginService.isAuthorized(authorizedRoles)) {
                    $rootScope.$broadcast('notAuthorized');
                }
            }
        });
    }
]);
在我的主控制器中:
    $scope.$on('notAuthorized', function(){
        $location.path('/forbidden');
    });
注意:angular 站点上有一些关于这个问题的讨论,尚未解决:https :
 //github.com/angular/angular.js/pull/4192
编辑:
要回答评论,这里是有关 LoginService 工作的更多信息。它包含3个功能:
- login()(名称具有误导性)向服务器发出请求以获取有关(以前)登录用户的信息。还有另一个登录页面,它只是填充服务器中的当前用户状态(使用 SpringSecurity 框架)。我的 Web 服务并不是真正的无状态,但我更愿意让那个著名的框架处理我的安全性。
 
- isAuthenticated() 只搜索客户端 Session 是否填充了数据,这意味着它之前已经过身份验证 (*)
 
- isAuthorized() 处理访问权限(超出本主题的范围)。
 
(*) 当路线改变时,我的会话被填充。我已覆盖 then when() 方法以在为空时填充会话。
这是代码:
services.factory('LoginService', ['$http', 'Session', '$q',
function($http, Session, $q){
    return {
        login: function () {
            var defer = $q.defer();
            $http({method: 'GET', url: restBaseUrl + '/currentUser'})
                .success(function (data) {
                    defer.resolve(data);
                });
            return defer.promise;
        },
        isAuthenticated: function () {
            return !!Session.userLogin;
        },
        isAuthorized: function (authorizedRoles) {
            if (!angular.isArray(authorizedRoles)) {
                authorizedRoles = [authorizedRoles];
            }
            return (this.isAuthenticated() &&  authorizedRoles.indexOf(Session.userRole) !== -1);
        }
    };
}]);
myApp.service('Session', ['$rootScope',
    this.create = function (userId,userLogin, userRole, userMail, userName, userLastName, userLanguage) {
        //User info
        this.userId = userId;
        this.userLogin = userLogin;
        this.userRole = userRole;
        this.userMail = userMail;
        this.userName = userName;
        this.userLastName = userLastName;
        this.userLanguage = userLanguage;
    };
    this.destroy = function () {
        this.userId = null;
        this.userLogin = null;
        this.userRole = null;
        this.userMail = null;
        this.userName = null;
        this.userLastName = null;
        this.userLanguage = null;
        sessionStorage.clear();
    };
    return this;
}]);
myApp.config(['$routeProvider', 'USER_ROLES', function ($routeProvider, USER_ROLES) {
    $routeProvider.accessWhen = function (path, route) {
        if (route.resolve == null) {
            route.resolve = {
                user: ['LoginService','Session',function (LoginService, Session) {
                    if (!LoginService.isAuthenticated())
                        return LoginService.login().then(function (data) {
                            Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
                            return data;
                        });
                }]
            }
        } else {
            for (key in route.resolve) {
                var func = route.resolve[key];
                route.resolve[key] = ['LoginService','Session','$injector',function (LoginService, Session, $injector) {
                    if (!LoginService.isAuthenticated())
                        return LoginService.login().then(function (data) {
                            Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
                            return func(Session, $injector);
                        });
                    else
                        return func(Session, $injector);
                }];
            }
        }
    return $routeProvider.when(path, route);
    };
    //use accessWhen instead of when
    $routeProvider.
        accessWhen('/home', {
            templateUrl: 'partials/dashboard.html',
            controller: 'DashboardCtrl',
            data: {authorizedRoles: [USER_ROLES.superAdmin, USER_ROLES.admin, USER_ROLES.system, USER_ROLES.user]},
            resolve: {nextEvents: function (Session, $injector) {
                $http = $injector.get('$http');
                return $http.get(actionBaseUrl + '/devices/nextEvents', {
                    params: {
                        userId: Session.userId, batch: {rows: 5, page: 1}
                    },
                    isArray: true}).then(function success(response) {
                    return response.data;
                });
            }
        }
    })
    ...
    .otherwise({
        redirectTo: '/home'
    });
}]);