Authentification
La manière la plus courante dans la conception des autorisations est le contrôle d'accès basé sur le rôle de RBAC. L'idée de base est que diverses autorisations pour les opérations système ne sont pas directement accordées aux utilisateurs spécifiques, mais plutôt pour établir une collection de rôles entre l'ensemble d'utilisateurs et l'ensemble d'autorisation. Chaque rôle correspond à un ensemble d'autorisations correspondant.
Une fois que l'utilisateur a été attribué le rôle approprié, l'utilisateur a toutes les autorisations opérationnelles pour le rôle. L'avantage de cela est qu'il n'est pas nécessaire d'attribuer des autorisations chaque fois qu'un utilisateur est créé, attribuez simplement le rôle correspondant de l'utilisateur, et les modifications d'autorisation du rôle sont bien inférieures à celles des modifications d'autorisation de l'utilisateur, ce qui simplifiera la gestion de l'autorisation de l'utilisateur et réduira les frais généraux du système.
Dans une application d'une seule page construite par Angular, nous devons faire des choses supplémentaires pour implémenter une telle architecture. Du point de vue global du projet, il y a environ 3 endroits auxquels les ingénieurs frontaux doivent faire face.
1. Traitement de l'interface utilisateur (à juger si un contenu sur la page est affiché en fonction des autorisations appartenant à l'utilisateur)
2. Traitement de routage (lorsque l'utilisateur accède à une URL à laquelle il n'a pas l'autorisation d'accéder, il passe à une page avec un message d'erreur)
3. Traitement de la demande HTTP (lorsque nous envoyons une demande de données, si l'état renvoyé est 401 ou 403, il est généralement redirigé vers une page avec un message d'erreur)
Implémentation du contrôle de l'identité d'accès
Tout d'abord, vous devez obtenir toutes les autorisations de l'utilisateur actuel avant le début d'Angular, puis le moyen le plus élégant est de stocker cette relation de cartographie via un service. Pour savoir si le contenu d'une page est affiché en fonction des autorisations par l'interface utilisateur. Après les traitements, nous devons ajouter un attribut "autorisation" supplémentaire pour ajouter un itinéraire lors de l'ajout d'un itinéraire, et lui attribuer une valeur pour indiquer quels rôles avec les autorisations peuvent sauter sur cette URL, puis écouter l'événement RouteCheangeStart via Angular pour vérifier si l'utilisateur actuel a accès à cette URL. Enfin, un intercepteur HTTP est nécessaire pour surveiller lorsque l'état renvoyé par une demande est 401 ou 403, passez à la page à une page d'invite d'erreur. C'est à peu près ce que c'est, il semble un peu trop, mais c'est en fait très facile à gérer.
Return 401, exécuter LoginCtrl, return 403, exécuter PermissionCtrl.
Obtenez la relation de cartographie de l'autorisation avant les courses angulaires
Le projet angulaire est lancé par NG-App, mais dans certains cas, nous espérons que le projet angulaire sera sous notre contrôle. Par exemple, dans ce cas, j'espère obtenir toutes les relations de mappage d'autorisation de l'utilisateur actuellement connecté, puis de démarrer l'application angulaire. Heureusement, Angular lui-même fournit cette méthode, c'est-à-dire angular.bootstrap ().
var permissionlist; angular.Element (document) .ready (function () {$ .get ('/ api / userpermission', function (data) {permissionList = data; angular.bootstrap (document, ['app']);});});Ceux qui lisent attentivement peuvent remarquer que l'utilisation de $ .get () est utilisée ici, et il n'y a aucune erreur en utilisant jQuery au lieu de la ressource $ Angular ou de $ http, car pour le moment, Angular n'a pas encore commencé, et nous ne pouvons pas utiliser sa fonction.
Utilisez davantage le code ci-dessus pour mettre la relation de mappage obtenue dans un service en tant que variable globale.
// app.js var app = angular.module ('myapp', []), permissionlist; app.run (function (permissions) {permissions.setperMissions (permissionlist)}); angular.Element (document) .ready (function () {$ .get ('/ api / userpermission', function (data) {permissionList = data; angular.bootstrap (document, ['app']);});}); // Common_Service.js angular.module ('myApp') .factory ('Permisessions', fonction ($ rootscope) {var permissionList; RETOUR {setPerMissions: function (permissions) {permissionList = Permissions; $ Rootscope. $ Broadcast ('PermissionsChanged')}};});Après avoir obtenu l'ensemble des autorisations de l'utilisateur actuel, nous archivons cet ensemble dans le service correspondant, puis avons fait 2 autres choses:
(1) Stockez les autorisations dans les variables d'usine afin qu'elles soient toujours en mémoire, réalisant le rôle des variables globales, mais ne polluant pas l'espace de noms.
(2) Événement de diffusion via $ Broadcast, lorsque les autorisations changent.
1. Comment déterminer la puissance visible et cachée du composant d'interface utilisateur en fonction des autorisations
Ici, nous devons rédiger une directive nous-mêmes, qui affichera ou masquera des éléments en fonction des relations d'autorisation.
<! - Si l'utilisateur a modifier l'autorisation, afficher un lien -> <div has-permission = 'edit'> <a href = "/ # / cours / {{id}} / edit"> {{name}} </a> </div> <! - Si l'utilisateur n'a pas la permission d'édition puis affiche le texte unique has-permission = '! edit'> {{name}} </div>Ici, je vois une situation idéale que vous pouvez passer le nom d'autorisation de vérification de la propriété HAS-Permission, et si l'utilisateur actuel l'a, il sera affiché, et s'il y en a non, il sera caché.
angular.module ('myApp'). directive ('haspermission', fonction (autorisation) {return {link: function (scope, élément, attrs) {if (! _. isstring (attrs.haspermission) lance "la valeur de haspermission doit être une chaîne"; var value = attrs.haspermission.trim (); var notpermision if (notpermiseflag) {value = toggleVisibilityBasedonPermission ();Développez l'usine précédente:
angular.module ('myApp') .factory ('Permisessions', fonction ($ rootscope) {var permissionList; return {setPerMissions: function (permissions) {permissionlist = permissions; $ rootscope. $ Broadcast ('Permissions = permissiond'); _.2. Accès basé sur l'autorisation sur l'itinéraire
L'idée de cette partie de la mise en œuvre est la suivante: lorsque nous définissons un itinéraire, nous ajoutons un attribut d'autorisation, et la valeur de l'attribut est les autorisations dont nous avons pour accéder à l'URL actuelle. Ensuite, nous continuons à écouter les changements d'URL via l'événement Routechangestart. Chaque fois que nous modifions l'URL, vérifiez si l'URL à rediriger répond aux conditions, puis décidez si elle sera redirigée avec succès ou vers la page de l'invite d'erreur.
app.config (function ($ routeProvider) {$ RouteProvider .WHEN ('/', {templateUrl: 'vues / viewCourses.html', contrôleur: ', `` ViewCoursesCtrl'}) .when ',' / unauthorized ', {templateurl:' vues / error.html ', contrôleur:' errorcTrl '}) .WHEN ('/ Courses /: id / edit', {templateUrl: 'vues / editCourses.html', contrôleur: 'editCourses', permission: 'edit'});MainController.js ou indexController.js (en bref, c'est le contrôleur de couche parent)
app.Controller ('MainAppctrl', fonction ($ scope, $ localisation, autorisation) {$ scope. $ on ('$ routechangestart', fonction (scope, suivant, courant) {var permission = next. });});L'affaire écrite avant est toujours utilisée ici, et ces choses sont très réutilisables. C'est fait. Avant chaque avion de vue, jugez simplement s'il a la permission de sauter dans le contrôleur du conteneur parent.
3. Traitement de la demande HTTP
Cela devrait être relativement facile à gérer, et l'idée est très simple. Étant donné que les applications angulaires recommandent des excuses de style Restful, l'utilisation du protocole HTTP est très claire. Si le code d'état renvoyé par la demande est 401 ou 403, cela signifie qu'il n'y a pas d'autorisation, vous pouvez donc simplement passer à la page d'invite d'erreur correspondante.
Bien sûr, nous ne pouvons pas vérifier et transmettre manuellement chaque demande une fois, nous devons donc certainement avoir besoin d'un filtre total. Le code est le suivant:
angular.module ('myapp') .config (function ($ httpprovider) {$ httprovider.Responseinterceptors.push ('SecurityInterceptor');}) .Provider ('SecurityInterceptor', function () {this. $ get = function ($ location, $ q) {return function (promesse) {return promew. if (Response.status === 403 || Response.status === 401) {$ localisation.path ('/ Unauthorized');En écrivant ceci, vous pouvez presque réaliser la gestion de l'autorisation et le contrôle de la partie frontale de ce mode de séparation frontale.
Vérification du formulaire
Directive de vérification frontale angularjs
var rcSUBMitDirective = {'rcSubmit': function ($ parse) {return {restrict: "a", require: ["rcsubmit", "form"], contrôleur: function () {this.atempted = false; var formController = null; this.setATTempted = function () {this.atTempted = true; }; this.setFormController = function (contrôleur) {formController = contrôleur; }; this.needsAttention = function (fieldModelController) {if (! FormController) return false; if (fieldModelController) {return fieldModelController. $ invalid && (fieldModelController. $ sale || this.atempted); } else {return formController && formController. $ invalid && (formatroller. $ sale || this.atTempted); }}; }, compiler: function () {return {pre: function (scope, formagement, attributs, contrôlers) {var soumidController = contrôlers [0]; var formController = contrôlers.length> 1? contrôleurs [1]: null; PoumleController.SetFormController (FormController); scope.rc = scope.rc || {}; scope.rc [attributs.name] = soumisController; }, post: fonction (étendue, formation, attributs, contrôleurs) {var soumisController = Controllers [0]; var formController = contrôlers.length> 1? contrôleurs [1]: null; var fn = $ parse (attributs.rcSubmit); FormElement.Bind ("Soumider", fonction (événement) {soumisController.SetAtTempted (); if (! Scope. $$ phase) Scope. $ applique (); if (! FormController. $ Valid) RETOUR; SCOP. }}; }}; }}; }}; }}; }}; }}; }}; }};Vérification a été adoptée
<form name = "loginform" novalidate ng-app = "loginApp" ng-controlller = "LoginController" rc-sumit = "login ()"> <div ng-class = "{'has-error': rc.loginform.needSattention (Type de liginform.user)}"> <entrée = "USERNAM requis ng-model = "session.username" /> <span ng-show = "rc.form.needsAuttention (loginform.userName) && loginform.userName. $ error.Required"> requis </span> </v> <div ng-class = "{'has-error': rc.Loginform.ne name = "mot de passe" type = "mot de passe" placeholder = "mot de passe" requis ng-model = "session.password" /> <span ng-show = "rc.form.needsAntitention (LoginForm.Password) && loginform.password. </div> </ form>Le style est le suivant
Login () sera appelé après les passes de vérification frontale.