Rozwiązaniem jest transmitowanie zdarzenia „notAuthorized” i przechwytywanie go w głównym zakresie w celu ponownej zmiany lokalizacji. Myślę, że to nie jest najlepsze rozwiązanie, ale u mnie zadziałało:
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');
}
}
});
}
]);
aw moim głównym kontrolerze:
$scope.$on('notAuthorized', function(){
$location.path('/forbidden');
});
Uwaga: na stronie kątowej jest dyskusja na temat tego problemu, jeszcze nie rozwiązana:
https://github.com/angular/angular.js/pull/4192
EDYTOWAĆ:
Aby odpowiedzieć na komentarz, poniżej znajduje się więcej informacji o działaniu usługi LoginService. Zawiera 3 funkcje:
- login () (nazwa wprowadza w błąd) wysyła żądanie do serwera w celu uzyskania informacji o (wcześniej) zalogowanym użytkowniku. Istnieje inna strona logowania, która po prostu zapełnia bieżący stan użytkownika na serwerze (przy użyciu struktury SpringSecurity). Moje usługi sieciowe nie są tak naprawdę bezpaństwowe, ale wolałem pozwolić, aby ten słynny framework zajął się moim bezpieczeństwem.
- isAuthenticated () po prostu wyszukuje, czy sesja klienta jest wypełniona danymi, co oznacza, że została uwierzytelniona przed (*)
- isAuthorized () obsłużył prawa dostępu (poza zakresem tego tematu).
(*) Moja sesja jest zapełniana po zmianie trasy. Zastąpiłem metodę then when (), aby zapełniać sesję, gdy jest pusta.
Oto kod:
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) {
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);
};
$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'
});
}]);