Я создал репозиторий на github, в основном резюмирующий эту статью: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec
ng-login Репозиторий Github
Plunker
Я постараюсь объяснить как можно лучше, надеюсь, что помогу некоторым из вас:
(1) app.js: создание констант аутентификации в определении приложения.
var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
all : '*',
admin : 'admin',
editor : 'editor',
guest : 'guest'
}).constant('AUTH_EVENTS', {
loginSuccess : 'auth-login-success',
loginFailed : 'auth-login-failed',
logoutSuccess : 'auth-logout-success',
sessionTimeout : 'auth-session-timeout',
notAuthenticated : 'auth-not-authenticated',
notAuthorized : 'auth-not-authorized'
})
(2) Служба аутентификации : все следующие функции реализованы в службе auth.js. Служба $ http используется для связи с сервером для процедур аутентификации. Также содержит функции по авторизации, то есть если пользователю разрешено совершать определенное действие.
angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS',
function($http, $rootScope, $window, Session, AUTH_EVENTS) {
authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]
return authService;
} ]);
(3) Сессия: синглтон для хранения пользовательских данных. Реализация здесь зависит от вас.
angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {
this.create = function(user) {
this.user = user;
this.userRole = user.userRole;
};
this.destroy = function() {
this.user = null;
this.userRole = null;
};
return this;
});
(4) Родительский контроллер: считайте это «основной» функцией вашего приложения, все контроллеры наследуются от этого контроллера, и это основа аутентификации этого приложения.
<body ng-controller="ParentController">
[...]
</body>
(5) Контроль доступа: чтобы запретить доступ на определенных маршрутах, необходимо выполнить 2 шага:
a) Добавьте данные о ролях, которым разрешен доступ к каждому маршруту, в сервисе $ stateProvider ui router, как показано ниже (то же самое может работать и для ngRoute).
.config(function ($stateProvider, USER_ROLES) {
$stateProvider.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
data: {
authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
}
});
})
б) В $ rootScope. $ on ('$ stateChangeStart') добавьте функцию для предотвращения изменения состояния, если пользователь не авторизован.
$rootScope.$on('$stateChangeStart', function (event, next) {
var authorizedRoles = next.data.authorizedRoles;
if (!Auth.isAuthorized(authorizedRoles)) {
event.preventDefault();
if (Auth.isAuthenticated()) {
// user is not allowed
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
} else {
// user is not logged in
$rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
}
}
});
(6) Перехватчик аутентификации: это реализовано, но не может быть проверено в рамках этого кода. После каждого запроса $ http этот перехватчик проверяет код состояния, если возвращается одно из следующих, то он транслирует событие, чтобы заставить пользователя снова войти в систему.
angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
return {
responseError : function(response) {
$rootScope.$broadcast({
401 : AUTH_EVENTS.notAuthenticated,
403 : AUTH_EVENTS.notAuthorized,
419 : AUTH_EVENTS.sessionTimeout,
440 : AUTH_EVENTS.sessionTimeout
}[response.status], response);
return $q.reject(response);
}
};
} ]);
PS Ошибку с автозаполнением данных формы, о которой говорилось в 1-й статье, можно легко избежать, добавив директиву, которая включена в directives.js.
PS2 Этот код может быть легко изменен пользователем, чтобы разрешить просмотр различных маршрутов или отображение содержимого, которое не предназначалось для отображения. Логика ДОЛЖНА быть реализована на стороне сервера, это просто способ правильно показать вещи в вашем ng-приложении.