AngularJS + UI Router: проверка авторизации и прав доступа
Если ваше приложение предполагает авторизацию пользователей и/или проверку прав доступа, то вам придется либо изобретать велосипед, либо гуглить в поисках подходящего решения. В принципе, я тоже это делал. В итоге я принял приемлемым для себя описанный ниже вариант.ПредпосылкиИнформацию об авторизованном пользователе я решил хранить в sessionStorage, копируя её при запуске приложения в $rootScope. Также по рекомендации авторов UI Router я храню в $rootScope значения объекты $state и $stateParam, для удобного доступа. Информацию же о доступе к тому или иному состоянию можно передавать через блок data при описании самого состояния. Поскольку в моем приложении везде закрыт доступ, я решил идти от обратного и добавлять значение noLogin = true для состояний, которые не требуют авторизации, например страницы ввода логина, восстановления пароля или регистрации. angular.module ('myApp.auth', [ 'ui.router' ]) .config (['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state ('auth', {
url: '/auth',
abstract: true,
template: '
.state ('auth.login', { url: '/login', templateUrl: 'src/auth/partials/login.html', data: { 'noLogin': true } }); ]); Создание сервиса для пре-роутинга Проверять авторизацию и права доступа нужно в самом начале, до работы роутера, перед тем, как он отправит посетителя на запрошенное состояние (предполагается, что вы знаете, что UI Router управляет не положениями, а состояниями. Больше читайте в официальной документации). Хороший способ это сделать — повесить слушателя на событие $stateChangeStart в методе run () вашего главного модуля. Чтобы не захламлять функционалом тело метода, который может быть объемным и сложным, я вынес его в отдельный сервис, в методе run () я просто вызываю метод сервиса. Думаю, дальше объяснения не понадобятся. angular.module ('myApp.auth') .service ('SessionService', [ '$injector', function ($injector) { «use strict»;
this.checkAccess = function (event, toState, toParams, fromState, fromParams) { var $scope = $injector.get ('$rootScope'), $sessionStorage = $injector.get ('$sessionStorage');
if (toState.data!== undefined) { if (toState.data.noLogin!== undefined && toState.data.noLogin) { // если нужно, выполняйте здесь какие-то действия // перед входом без авторизации } } else { // вход с авторизацией if ($sessionStorage.user) { $scope.$root.user = $sessionStorage.user; } else { // если пользователь не авторизован — отправляем на страницу авторизации event.preventDefault (); $scope.$state.go ('auth.login'); } } }; } ]); Собираем все вместе Ну и остается последний штрих, чтобы все это заработало — повесить слушателя на событие сервиса $state. angular.module ('myApp', [ 'myApp.auth', 'ui.router', 'ngStorage' ])
.run ([ '$rootScope', '$state', '$stateParams', 'SessionService', function ($rootScope, $state, $stateParams, SessionService) {
$rootScope.$state = $state; $rootScope.$stateParams = $stateParams;
$rootScope.user = null;
// Здесь мы будем проверять авторизацию $rootScope.$on ('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { SessionService.checkAccess (event, toState, toParams, fromState, fromParams); } ); } ]) Заключение Думаю, данного примера вполне достаточно, чтобы использовать его как идею и написать собственную авторизацию и проверку прав доступа с какими угодно плюшками. Например, в тот же блок data при описании состояния вы можете передавать какие-либо RBAC-правила, а затем проверять их в своем сервисе.