Implementation of Role-based browser access control in AngularJs

Source: Internet
Author: User
AngularJs's role-based front-end access control implementation only records the implementation of front-end access control because of its rich experience in backend access control. Please note that the front-end can only achieve display control at most! Security is not guaranteed, so the backend must implement access control!

Role-Based Access Control requires two levels of access control:

Control page route jump. Users without permissions cannot jump to the specified url.

Display Control of page elements. Users without corresponding permissions cannot see this element

But before that, we have another important thing to do.

Store user information

What we need to do first is not related to access control. First, we need to save user information. Includes basic user information, such as user name, real name, and user role. The following is the data structure:

User = {
Username :"",
Realname :"",
Role :""
}

The entire user is stored during storage, but where does it exist? Considering that it must be accessible on any page, the first response is to store it in rootScope, but we should try to avoid using rootScope; in addition, we can store these two solutions in the top-level controller or global constant, but their problem is that once the page is refreshed, it doesn't matter if you use $ rootScope ). Considering that the life cycle of the user variable should be the same as that of the session, I used SessionStorage.

When creating a controller, you need to add $ sessionStorage:

app.controller('controller',['$sessionStorage', function($sessionStorage){}]);

After successful logon, store the user in SessionStorage:

$sessionStorage.USER = user;

Now, you can get user information through $ sessionStorage.

user = $sessionStorage.USER;

Control page route jump

Next we will start to implement the first point: control the page route jump.

It is easier to achieve the first point. When Angular routes change, the $ stateChangeStart event is triggered (I use stateProvider, so I listen to stateChangeStart. If the route or location is used, listen to the corresponding events), listen to this event, and make permission judgments based on the access url and user role, such as logon judgment, to access the url, You need to log on to the logon page.

First, write an auth service for permission authentication:

/*** Role-Based Access Control */App. service ("auth", ["$ http", "$ sessionStorage", function ($ http, $ sessionStorage) {var roles = []; // role table obtained from the backend database // role permission Url ing table obtained from the backend. The structure is {"role": ["/page1 ", "/page2"……]} Var urlPermissions = {}; // obtain the function () from the backend {// This is convenient for testing and has been assigned a value directly. The following example is used only for the purpose, try to simplify roles = ["admin", "user"] urlPermissions = {// The administrator can access the "admin": ["*"], // normal users can access all interfaces (logon, registration, and other pages) in the page path and the system Homepage "user": ["page. * "," app. index "," app. detail "]}) (); function convertState (state) {return state. replace (". ","\\\. "). replace ("*",". * ");} return {// whether you have the permission to access a url isAccessUrl: function (url) {var user = $ sessionStorage. USER; for (var role in roles) {if (user. role. toLowerCase () = roles [role]. toLowerCase () {console. log (urlPermissions [roles [role]) for (I in urlPermissions [roles [role]) {var regx = eval ("/" + convertState (urlPermissions [roles [role] [I]) + "/"); console. log (regx + "" + url) if (regx. test (url) {return true ;}}} return false ;}}])

Roles is a role that is obtained from the background. urlPermissions is a list of URLs accessible to each role. It is also obtained from the background and can be configured in the background. In this way, each time a role is added, We can dynamically configure access permissions for it.

The most important thing is the isAccessUrl method. After the url is imported, isAccessUrl first obtains user information through $ sessionStorage, obtains the user role, and then checks whether the user role is in the role table. If the user role is in the role table, check whether the role has the permission to access the url. When we configure the status in the background, we directly specify the status, but if there is no wildcard character, then each page needs to write a url, so the wildcard function is added, then, convert each url in the url list to a regular expression and verify the configuration.

Finally, listen to the event $ stateChangeStart in run:

App. run (["$ rootScope", '$ State', "auth", "$ sessionStorage", function ($ rootScope, $ state, auth, $ sessionStorage) {$ rootScope. $ on ('$ stateChangeStart', function (event, toState, toParams, fromState, fromParams) {// route access control if (toState. name! = "Page. login "&&! Auth. isAccessUrl (toState. name) {// check whether logon is required: var user = $ sessionStorage. USER; if (user = null) {event. preventDefault (); $ state. go ("page. login "); return;} event. preventDefault (); $ state. go ("page. error ") ;}}) ;}])

Now we have implemented url access control.

Display Control of page elements

As for the second point, my solution is custom commands. The following is an example:

Note: The role is not passed in, but the permission. This is because user roles can be dynamically expanded. If a role is written here to access this element, it will be a great deal of trouble for every new role to be added in the future, because you have to modify the code one by one. The code for zg-access is as follows:

/*** Element-level access control command */App. directive ("zgAccess", function ($ sessionStorage, $ http) {var roles = []; // role var elemPermissions ={}; // role element permission ing table, for example, {"role": {"SEARCH" }}, role has this SEARCH permission // obtain the function () in the background {// For convenience, generate roles = ["admin", "user", "visitor"]; elemPermission = {"admin": ["*"], "user ": ["SEARCH"], "visitor": []}) (); console. log ("zg-access"); return {restrict: 'A', compile: function (element, attr) {// The initial state is invisible. none, there are also disbaled and OK available, three statuses var level = "none"; console. log (attr) if (attr & attr ["zgAccessLevel"]) {level = attr ["zgAccessLevel"];} switch (level) {case "none": element. hide (); break; case "disabled": element. attr ("disabled", ""); break;} // obtain the element permission var access = attr ["zgAccess"]; // upload this permission to the backend database (function () {// upload}) (); return function (scope, element) {// determine whether the user has the permission var user = $ sessionStorage. USER; if (user = null | angular. equals ({}, user) {user ={}; user. role = "visitor";} var role = user. role. toLowerCase (); console. log (roles); for (var I in roles) {var tmp = roles [I]. toLowerCase (); if (role = tmp) {tmp = elemPermission [role]; console. log (tmp) for (var j in tmp) {console. log (tmp [j] + "" + access); if (access. toLowerCase () = tmp [j]. toLowerCase () {element. removeAttr ("disabled"); element. show ();}}}}};}}})

ZgAccessLevel is an attribute used to control the level. If it is none (the default value is none), no element is displayed. If it is disbaled, the element is unavailable (such as the Button is unavailable ).

The following is an element example:

Search

If you log on as admin or user, the Search button is unavailable.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.