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: '<ui-view>'         })        .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-правила, а затем проверять их в своем сервисе.

Что вы используете для управления маршрутами в Angular JS?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Проголосовало 182 человека. Воздержалось 68 человек.

ссылка на оригинал статьи http://habrahabr.ru/post/245049/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *