J'ai créé un dépôt github résumant cet article en gros: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec
Repo Github ng-login
Plunker
Je vais essayer d'expliquer le mieux possible, j'espère aider certains d'entre vous là-bas:
(1) app.js: Création de constantes d'authentification sur la définition d'application
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) Service Auth: Toutes les fonctions suivantes sont implémentées dans le service auth.js. Le service $ http est utilisé pour communiquer avec le serveur pour les procédures d'authentification. Contient également des fonctions sur l'autorisation, c'est-à-dire si l'utilisateur est autorisé à effectuer une certaine action.
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) Session: Un singleton pour conserver les données utilisateur. La mise en œuvre ici dépend de vous.
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) Contrôleur parent: considérez cela comme la fonction "principale" de votre application, tous les contrôleurs héritent de ce contrôleur, et c'est l'épine dorsale de l'authentification de cette application.
<body ng-controller="ParentController">
[...]
</body>
(5) Contrôle d'accès: pour refuser l'accès sur certaines routes, 2 étapes doivent être mises en œuvre:
a) Ajoutez les données des rôles autorisés à accéder à chaque route, sur le service $ stateProvider du routeur de l'interface utilisateur, comme on peut le voir ci-dessous (cela peut fonctionner pour ngRoute).
.config(function ($stateProvider, USER_ROLES) {
$stateProvider.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
data: {
authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
}
});
})
b) Sur $ rootScope. $ on ('$ stateChangeStart') ajoutez la fonction pour empêcher le changement d'état si l'utilisateur n'est pas autorisé.
$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) Intercepteur d'authentification: Ceci est implémenté, mais ne peut pas être vérifié sur la portée de ce code. Après chaque requête $ http, cet intercepteur vérifie le code d'état, si l'un des éléments ci-dessous est renvoyé, il diffuse un événement pour forcer l'utilisateur à se reconnecter.
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 Un bogue avec le remplissage automatique des données du formulaire comme indiqué dans le premier article peut être facilement évité en ajoutant la directive qui est incluse dans directives.js.
PS2 Ce code peut être facilement modifié par l'utilisateur, pour permettre de voir différents itinéraires ou d'afficher du contenu qui n'était pas destiné à être affiché. La logique DOIT être implémentée côté serveur, c'est juste un moyen d'afficher correctement les choses sur votre ng-app.