ASP. NET core MVC rights control: assigning Permissions

Source: Internet
Author: User

The previous article describes how to do permission control, that is, access to the controller or method, the need for the current user must have specific permissions, but how to assign permissions in the program? The following describes how to use the Microsoft.AspNetCore.Identity.EntityFrameworkCore framework for permission assignment.

Before we introduce the allocation method, we must understand the permission relationship, which involves three objects: the user, the role, the permissions, the permissions assigned to the role, the role is assigned to the user, and when a user belongs to a role, the user has a list of permissions that the role contains, such as now has an information manager role, This role includes the ability to delete information, and when the Zhang San user has the information Administrator role, Zhang San has the right to delete the information. In some special scenarios, permissions can also be directly assigned to the user, which means that specific permissions can be directly assigned to the user, bypassing the role. This support is provided in the Microsoft.AspNetCore.Identity.EntityFrameworkCore framework.

First introduce the main business object classes in the framework:

Identityuser: Represents a user information

Identityrole: Represents a role information

Identityroleclaim<tkey>: Indicates the permissions that the role has

Identityuserclaim<tkey>: Indicates the permissions that the user has

Identityuserrole<tkey>: Represents a user role relationship

After understanding the basic concepts, let's look at how to assign permissions.

1, assigning Permissions to roles: The RoleManager class is provided in Microsoft.AspNetCore.Identity.EntityFrameworkCore, which provides methods for assigning permissions to roles:

 Task<identityresult> Addclaimasync (trole role, Claim Claim)

  The first parameter represents the corresponding role object, and the second parameter represents a permission information

2, assigning permissions to users: The Usermanager class is provided in Microsoft.AspNetCore.Identity.EntityFrameworkCore, which provides methods for assigning permissions to users:

Task<identityresult> Addclaimasync (TUser user, Claim Claim)

  The first parameter represents the corresponding user object, and the second parameter represents a permission information

3, assigning users to roles: Use the same Usermanager class, using the method:

Addtoroleasync (TUser User, String role)

The first parameter represents the user object, and the second is the name of the role

4, get the list of permissions that the role currently has:

 Task<ilist<claim>> Rolemanager.getclaimsasync (trole role)

5, gets the list of permissions that the user currently has:

 Task<ilist<claim>> Usermanager.getclaimsasync (TUser user)

In this way, the whole process of permission assignment can be completed, and then the system realizes the complete permission control logic by combining the previous permission control method.

Now the question comes, where does the permission list come from? In general, after a business system function is determined, the corresponding permissions list is naturally determined, and then to assign permissions to the role, assign permissions to the user's function, only need to put all the permissions listed on the page to choose, as follows:

You can save the selected data by calling the corresponding method.

The problem has been solved, but the new problem has come again. If a business function point is very much, nature will lead to a lot of permissions, if you write to the page completely by hand, then the natural workload will be very large, and the business system may be constantly changing, this time will also go to constantly modify the rights allocation page, this is not a good way, I would like to tell you a way I think, not necessarily the best, but can save a lot of things.

The first thing we need to solve is how to quickly generate this list of rights configurations.

The idea is to transform Authorizeattribute, to add permission description information on the basis of this feature, and to use permission description information as policy. Directly below the code:

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = True, inherited =true)]
   //class name can be changed, because I take the system operation as a resource to managepublic class Resourceattribute:authorizeattribute {private string _resoucename; private string _action; Public ResourceAttribute (string name) {if (string. IsNullOrEmpty (name)) {throw new ArgumentNullException (nameof (name)); } _resoucename = name;//Set resource name to policy namePolicy = _resoucename; } public string GetResource () {return _resoucename; } public string Action {get {return _action; } set {_action = value; if (!string. IsNullOrEmpty (value)) {
          //Assemble the resource name and operation name into policyPolicy = _resoucename + "-" + value; } } } }

  

Class is already defined, let's look at how to use it, because it is an attribute definition, so you can use the following structure on a controller class or method:

[Resource ("organization structure", Action = "Add Department")]

The basic work has been done here, and there are two more issues to be solved:

1,policy now only has the name configured, but the specific validation rule is not defined

2, how to get all the permissions list

First of all, the previous article describes that the policy needs to be configured in startup with Addauthorization, but now we are not doing such a step, so the permissions will not work at this point. When the framework is authenticated, it relies on a iauthorizationpolicyprovider to get specific rules based on the policy name, and naturally we think of customizing a iauthorizationpolicyprovider implementation, The code is as follows:

public class Resourceauthorizationpolicyprovider:iauthorizationpolicyprovider {private authorizationoptions        _options; Public Resourceauthorizationpolicyprovider (ioptions<authorizationoptions> options) {if (options =            = null) {throw new ArgumentNullException (nameof (options)); } _options = Options.        Value; } public task<authorizationpolicy> Getdefaultpolicyasync () {return Task.fromresult (_option        S.defaultpolicy); } Public task<authorizationpolicy> Getpolicyasync (string policyName) {Authorizationpolic Y policy = _options. GetPolicy (PolicyName);
       //Because the name of our policy is actually the corresponding permission name, you can return the required validation rules with the following logicif (policy = = null) {string[] resourcevalues = Policyname.split (new char[] {'-'}, Stringsplit Options.none); if (resourcevalues.length = = 1) {_options. Addpolicy (policyName, builder = {Builder. Addrequirements (New Claimsauthorizationrequirement (resourcevalues[0], null)); }); } else {_options. Addpolicy (policyName, builder = {Builder. Addrequirements (New Claimsauthorizationrequirement (Resourcevalues[0], new string[] {resourcevalues[1]}); }); }} return Task.fromresult (_options. GetPolicy (PolicyName)); } }

With the implementation of Iauthorizationpolicyprovider, we need to register in the Startup.cs configureservices (iservicecollection Services) method, as follows:

Services. TryAdd (Servicedescriptor.transient<iauthorizationpolicyprovider, resourceauthorizationpolicyprovider> ());

To look at the second question, we have defined the permission information on the controller or method, the key is how we get the permission list from these features, and use it in the future for permission assignment. A class resolution mechanism is provided in ASP. Iapplicationmodelprovider, this dependency information is much more, here is not too much introduction, follow-up I will open a series alone, introduce the internal mechanism of ASP.

Directly on the code

public class Resourceapplicationmodelprovider:iapplicationmodelprovider {private ReadOnly iauthorizationpolic        Yprovider _policyprovider;  Public Resourceapplicationmodelprovider (Iauthorizationpolicyprovider policyprovider) {_policyprovider =        Policyprovider;        } public void onprovidersexecuted (Applicationmodelprovidercontext context) {}            public void onprovidersexecuting (Applicationmodelprovidercontext context) {if (context = = null)            {throw new ArgumentNullException (nameof (context)); } list<resourceattribute> attributedata = new list<resourceattribute> ();
         //loop to get all the controllersforeach (var controllermodel in context. Result.controllers) {
        //Get ResourceAttributevar resourcedata = controllermodel.attributes.oftype<resourceattribute> (). ToArray (); if (Resourcedata.length > 0) {attributedata.addrange (resourcedata); }//Cycle Controller methodforeach (Var actionmodel in controllermodel.actions) {
//Get the method ResourceAttributevar actionresourcedata = actionmodel.attributes.oftype<resourceattribute> (). ToArray (); if (Actionresourcedata.length > 0) {attributedata.addrange (actionresourcedat a); } } }//write all resourceattribute information into a global resourcedata, resourcedata can be used elsewhere, resourcedata define the followingforeach (var item in attributedata) {Resourcedata.addresource (item. GetResource (), item. Action); }} public int Order {get {return-1000 + 11;}} }

Resourcedata is defined as follows

public class Resourcedata    {        static resourcedata ()        {            Resources = new dictionary<string, list< String>> ();        }        public static void AddResource (string name)        {            AddResource (name, "");        }        public static void AddResource (string name,string action)        {            if (string. IsNullOrEmpty (name))            {                return;            }            if (! Resources.containskey (name))            {                resources.add (name, New list<string> ());            }            if (!string. IsNullOrEmpty (action) &&! Resources[name]. Contains (Action))            {                resources[name]. ADD (action);            }        }        public static dictionary<string, list<string>> Resources {get; set;}    }

Then register the Iapplicationmodelprovider we just defined in startup:

Services. Tryaddenumerable (Servicedescriptor.transient<iapplicationmodelprovider, resourceapplicationmodelprovider> ());

Then, on the Rights Assignment page, all the permission information is obtained through resourcedata.resources, and then it can be displayed directly on the page by loop.

Finally finished, haha ~ ~

 

  

  

  

ASP. NET core MVC rights control: assigning Permissions

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.