Access control in Angularjs in front-end separation mode-based on RBAC

Source: Internet
Author: User

In the design of permissions is more common is RBAC role-based access control, the basic idea is that the system operation of the various permissions are not directly granted to specific users, but in the user set and the set of permissions set up a role set. Each role corresponds to a set of appropriate permissions.

Once the user has been assigned the appropriate role, the user has all the permissions to operate on the role. The benefit of 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 has a much smaller permission change than the user's permission change, 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 lot more to implement such a architecture. From the overall project, there are about 3 places where front-end engineers need to process.

1. UI processing (depending on user-owned permissions, determine whether some content on the page is displayed)

2. Route processing (when a user accesses a URL that it does not have permission to access, jumps to the page of an error prompt)

3. HTTP request processing (when we send a data request, if the returned status is 401 or 401, then the page is usually redirected to an error prompt)

How is it implemented?

First you need to get all the permissions of the current user before the angular is started, and then the elegant way is to store this mapping relationship through a service. Whether the UI handles content on a page is displayed according to permissions, We should do it through a directive. When we're done with this, we also need to add an additional "permission" attribute to the route when we add it, and assign it a value that indicates what permissions the role can jump to the URL. The Routechangestart event is then monitored by angular to see if the current user has a checksum for this URL access. Finally, an HTTP interceptor is required to monitor when a request returns a status of 401 or 403, the jump page goes to an error prompt page.

In general the work is these, looks a bit more, in fact, one after another is quite good to deal with.

Get mappings to permission before angular runs

The angular project was launched through Ng-app, but in some cases we wanted the angular project to start under our control. For example, in this case, I want to get all the permission mappings to the currently logged-in user. Start the angular app again. Fortunately angular itself provides this way, namely Angular.bootstrap ().

var permissionlist;angular.element (document). Ready (function () {$.get ('/api/userpermission ', function (data) {    permissionlist = data;  Angular.bootstrap (document, [' App ']); });});

Looking at the careful person may notice that this is using $.get (), there is no wrong use of jquery instead of angular $resource or $http, because at this time angular has not started, its function we can not use.

Further use of the above code allows you to put the acquired mapping relationship into a service as a global variable to use.

 app.jsvar 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.jsangular.module (' myApp ')   .factory (' Permissions ', function  ($ Rootscope)  {    var permissionList;    return {       setpermissions: function (permissions)  {         permissionlist = permissions;        $ Rootscope. $broadcast (' permissionschanged ')       }   };   });

After we get the collection of permissions for the current user, we archive the collection to a corresponding service, and then do 2 things:

(1) The permissions is stored in the factory variable, so that it is always in memory, implementing global variables, but without polluting the namespace.

(2) by $broadcast broadcast event, when the permission changes.

How to determine whether a UI component is explicitly based on permissions

Here we need to write a directive, which will show or hide the elements according to the permission relationship.

<!--If The user has edit permission the show a link--><div has-permission= ' edit ' > <a href= "/#/courses/{{ ID}}/edit "> {name}}</a></div> <!--If the user doesn ' t has an edit permission then show Text Only (No Te the "!" before "Edit")--><div has-permission= '! Edit ' > {{name}}</div>

See here the more ideal situation is to clear a Has-permission property Check permission name, if the current user has the display, no is 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);     }  };});

Extend 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 () &NBSP;===&NBSP;PERMISSION&NBSP;&NBSP;&NBSP;&Nbsp;    });       }   };  }); 

Access by permission on a route

This part of the idea of implementation is this: when we define a route to add a permission property, the value of the property is what permissions to access the current URL. The URL changes are then monitored through the Routechangestart event. Each time you change the URL, To verify that the URL you are currently jumping to matches the criteria, and then decide whether to jump to the wrong prompt or jump to the error page.

Router.js:

App. Config (function ($routeProvider) {$routeProvider. When ('/', {templateurl: ' views/viewcourses.html ', CO Ntroller: ' Viewcoursesctrl '}). When ('/unauthorized ', {templateurl: ' views/error.html ', Controller: ' Erro      Rctrl '}). When ('/courses/:id/edit ', {templateurl: ' views/editcourses.html ', controller: ' Editcourses ', Permission: ' Edit '});

Maincontroller.js or Indexcontroller.js (in short, the parent 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 in the previously written haspermission, these things are highly reusable. This is done, in each view of the route jump, in the parent container controller to determine whether it has the right to jump.

HTTP request Processing

This should be relatively good to deal with, the idea of thinking is very simple. Because the Angular app recommends restful style excuses, the use of the HTTP protocol is clear. For the status code returned by the request, if 401 or 403, it means that there is no permission. You can jump to the corresponding error prompt page.

     Of course we can't go to the Manual check and forward 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)  {         return promise.then (null, function (response)  {           if (response.status === 403 | |  response.status === 401)  {              $location. Path ('/unauthorized ');           }           return  $q. Reject (response);         });      };    };  }); 

It's almost there. In this front-end separation mode, the front-end section of the Rights Management and control

Article Source: http://www.open-open.com/lib/view/open1408084201582.html

Access control in Angularjs in front-end separation mode-based on RBAC

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.