authentication
permissions are more common in the design of RBAC role-based access control, the basic idea is that the various permissions on the operation of the system are not directly to the specific user, but to set up a role between the user set and the set of permissions. Each role corresponds to a set of appropriate permissions.
Once the user is assigned the appropriate role, the user has all the action rights for the role. The advantage of doing this is that you do not have to assign permissions every time you create a user, as long as you assign the appropriate role to the user, and the role changes more than the user's permissions, which simplifies the user's rights management and reduces the overhead of the system.
in a single page application built by angular, we need to do a little extra work. From the overall project, about 3 places, front-end engineers need to deal with.
1. UI processing (depending on the permissions the user has, to determine if something on the page is displayed)
2. Route processing (jumps to a page of error prompts when a user accesses a URL that it does not have permission to access)
3. HTTP request processing (when we send a data request, if the status returned is 401 or 403, it is usually redirected to a page that is incorrectly prompted)
Implementation of Access Identity control
first you need to get all the permissions of the current user before angular starts, and then the more elegant way is to store the mapping relationship through a service. Whether the UI handles content on a page based on permissions, we should pass Over a directive to achieve. When this is done, we also need to add a "permission" attribute to add a route to it, and assign it to a role that indicates which permissions are available to jump the URL. The angular listens for the Routechangestart event to verify that the current user has access to this URL. Finally, an HTTP interceptor is required to monitor when a request returns a status of 401 or 403, Jump page to an error prompt page. The general work is these, looks a bit more, in fact, one or a good deal.
Returns 401, executes Loginctrl, and returns 403 execution Permissionctrl.
Gets the mapping relationship to the permission before angular runs
The angular project is launched through Ng-app, but in some cases we want the angular project to start in our control. For example, in this case, I would like to obtain all the permission mappings of the current logged-on user, and then start Angular's app. Fortunately angular itself offers this way, which is angular.bootstrap ().
var permissionlist;
Angular.element (document). Ready (function () {
$.get ('/api/userpermission ', function (data) {
permissionlist = data;
Angular.bootstrap (document, [' App ']);
});
People who look carefully may notice that there is a $.get (), and that there is no mistake in jquery instead of angular $resource or $http, because at this time angular has not yet started, its function we still can not use.
Further use of the above code can be used to place the acquired mapping relationship into a service as a global variable.
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 (' Permissions ', function ($rootScope) {
var Permissionlist;
return {
setpermissions:function (permissions) {
permissionlist = permissions;
$rootScope. $broadcast (' permissionschanged ')
}};
After getting the current user's set of permissions, we archive the collection into a corresponding service, and then do 2 more things:
(1) The permissions is stored in the factory variable so that it is always in memory to achieve the role of global variables, but there is no pollution namespace.
(2) Broadcast events through $broadcast, when permissions are changed.
1. How to determine the UI component based on permissions for explicit implicit
Here we need to write a directive ourselves, which displays or hides elements based on the permission relationship.
<!--If The user has edit permission the show a link-->
<div has-permission= ' edit ' >
<a href= '/#/co urses/{{ID}}/edit "> {{name}}</a>
</div>
<!--If the user doesn ' t have edit permission then s How to Text only (note the "Before" "Edit")-->
<div has-permission= '! Edit ' >
{{name}}}
</div>
Here we see the ideal situation is customs clearance a Has-permission property verifies the name of the permission, if the current user has it, it is not hidden.
Angular.module (' myApp '). Directive (' haspermission ', function (permissions) {return
{
link:function (scope, Element, Attrs) {
if (!_.isstring (attrs.haspermission))
throw "haspermission value must be a string";
var value = Attrs.hasPermission.trim ();
var notpermissionflag = value[0] = = '! ';
if (notpermissionflag) {
value = Value.slice (1). Trim ();
function Togglevisibilitybasedonpermission () {
var haspermission = permissions.haspermission (value);
if (haspermission &&!notpermissionflag | | |!haspermission && notpermissionflag)
element.show ();
else
element.hide ();
}
Togglevisibilitybasedonpermission ();
Scope. $on (' permissionschanged ', togglevisibilitybasedonpermission);
}};
Expand the previous factory:
Angular.module (' myApp ')
. Factory (' Permissions ', function ($rootScope) {
var permissionlist;
return {
setpermissions:function (permissions) {
permissionlist = permissions;
$rootScope. $broadcast (' permissionschanged ')
},
haspermission:function (permission) {
Permission = Permission.trim ();
Return _.some (permissionlist, function (item) {
if (_.isstring) (item. Name) return
item. Name.trim () = = Permission
});
}
};
2. Access by rights on the route
This part of the implementation of the idea is this: when we define a route to add a permission attribute, the value of the property is what permissions to access the current URL. And then through the routechangestart thing The item has been listening for URL changes. Each time the URL changes, to verify the current URL to jump to meet the criteria, and then decide whether to jump success or jump to the wrong prompt page.
App.config (function ($routeProvider) {
$routeProvider
. When ('/', {
templateurl: ' views/ Viewcourses.html ',
controller: ' Viewcoursesctrl '
})
. When ('/unauthorized ', {
templateurl: ' views/ Error.html ',
controller: ' Errorctrl '
})
. When ('/courses/:id/edit ', {
templateurl: ' views/ Editcourses.html ',
controller: ' editcourses ',
permission: ' Edit '
};
};
Maincontroller.js or Indexcontroller.js (in short, parent layer Controller)
App.controller (' Mainappctrl ', function ($scope, $location, permissions) {
$scope. $on (' $routeChangeStart ', function (scope, next, current) {
var permission = next.$ $route. permission;
if (_.isstring (permission) &&!permissions.haspermission (permission))
$location. Path ('/unauthorized ' );
});
});
This is still used to write the haspermission, these things are highly reusable. This is done, in each view route jump before the controller in the parent container to determine whether it has the right to jump.
3.HTTP Request Processing
this should be relatively good deal with the idea of thinking is also very simple. Because the angular application recommends a restful-style excuse, the use of the HTTP protocol is clear. For the status code returned by the request, if 401 or 403 means no permissions, Jump to the corresponding error message page can be.
Of course, we can't go through the manual checksum forwarding on every request, so we definitely need a total filter. The code is as follows:
Angular.module (' myApp ')
. config (function ($httpProvider) {
$httpProvider. Responseinterceptors.push (' Securityinterceptor ')
. Provider (' Securityinterceptor ', function () {this
. $get = function ($location, $q) {return
function (Promise) { C8/>return promise.then (NULL, function (response) {
if (Response.Status = = 403 | | response.status = = 401) {
$ Location.path ('/unauthorized ');
}
Return $q. Reject (response);}
);
};
};
Writing here is almost a way to achieve this in the front-end separation mode, the front part of the Rights management and control.
Form validation
ANGULARJS front-end verification directives
var rcsubmitdirective = {' Rcsubmit ': function ($parse) {return {restrict: "A", Require: ["Rcsubmit", ""? form
"], Controller:function () {this.attempted = false;
var formcontroller = null;
this.setattempted = function () {this.attempted = true;
};
This.setformcontroller = function (Controller) {Formcontroller = controller;
};
This.needsattention = function (Fieldmodelcontroller) {if (!formcontroller) return false; if (Fieldmodelcontroller) {return fieldmodelcontroller. $invalid && (fieldmodelcontroller. $dirty | | this.attem
pted); else {return Formcontroller && formcontroller. $invalid && (formcontroller. $dirty | | this.attempted)
;
}
}; }, Compile:function () {return {pre:function (scope, formelement, attributes, controllers) {var Submitcon
Troller = Controllers[0]; var formcontroller = controllers.length > 1?
CONTROLLERS[1]: null; Submitcontroller.setformcontRoller (Formcontroller); scope.rc = Scope.rc | |
{};
Scope.rc[attributes.name] = Submitcontroller;
}, Post:function (scope, formelement, attributes, controllers) {var submitcontroller = controllers[0]; var formcontroller = controllers.length > 1?
CONTROLLERS[1]: null;
var fn = $parse (attributes.rcsubmit);
Formelement.bind ("Submit", function (event) {submitcontroller.setattempted ();
if (!scope.$ $phase) scope. $apply ();
if (!formcontroller. $valid) return;
Scope. $apply (function () {fn (scope, {$event: event});
});
});
}
};
}
};
}
};
&NBSP
Validation through the
<form name= "LoginForm" novalidate ng-app= "Loginapp" ng-controller= "Logincontroller" rc-submit= "login ()" > <d IV class= "Form-group" ng-class= "{' Has-error ': Rc.loginForm.needsAttention (Loginform.username)}" > <input class = "Form-control" name= "username" type= "text" placeholder= "username" required ng-model= "Session.username"/> < Span class= "Help-block" ng-show= "Rc.form.needsAttention (loginform.username) && loginform.username.$ Error.required ">Required</span> </div> <div class=" Form-group "ng-class=" {' Has-error ': Rc.loginf Orm.needsattention (Loginform.password)} "> <input class= form-control" name= "password" type= "password" Placeh Older= "Password" required ng-model= "Session.password"/> <span class= "Help-block" ng-show= "Rc.form.needsAtte"
Ntion (Loginform.password) && Loginform.password. $error. Required ">Required</span> </div> <div class= "Form-group" > <button type= "Submit" class= "btn btn-primary pull-right" value= "login" title= "Login" > <SPAN>LOGIN</SPAN&G
T
</button> </div> </form>
The style is as follows
The front end verification is invoked by calling login ().