Asp.net core mvc permission control: assigning permissions and mvc permission Control

Source: Internet
Author: User

Asp.net core mvc permission control: assigning permissions and mvc permission Control

The previous article introduced how to implement permission control, that is, when accessing a controller or method, 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 to allocate permissions.

Before introducing the assignment method, we must understand the permission relationship. Three objects are involved: users, roles, permissions, and permissions assigned to roles. roles are assigned to users, when a user belongs to a role, the user has a list of permissions contained in the role. For example, there is an information administrator role that includes the Information deletion permission, after a user named Michael has the information administrator role, Michael has the permission to delete information. In some special scenarios, permissions can also be directly assigned to users, that is, some specific permissions can be directly assigned to users without passing through roles. Microsoft. AspNetCore. Identity. EntityFrameworkCore framework provides such support.

First, we will introduce the main business object classes in the framework:

IdentityUser: indicates a user.

IdentityRole: indicates a role.

IdentityRoleClaim <TKey>: indicates the role's permissions.

IdentityUserClaim <TKey>: indicates the user's permissions.

IdentityUserRole <TKey>: indicates the user role relationship.

 

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

1. Assign permissions to the role: Microsoft. AspNetCore. Identity. EntityFrameworkCore provides the RoleManager class, which provides the method to assign permissions to the role:

 Task <IdentityResult> AddClaimAsync (TRole role, Claim claim)

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

2. Assign permissions to the user: Microsoft. AspNetCore. Identity. EntityFrameworkCore provides the UserManager class, which provides the method to assign permissions to the user:

Task <IdentityResult> AddClaimAsync (TUser user, Claim claim)

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

3. assign a user to a role: the UserManager class is also used. The method is as follows:

AddToRoleAsync (TUser user, string role)

The first parameter indicates the user object, and the second parameter indicates the role name.

4. Obtain the current permissions of a role:

 Task <IList <Claim> RoleManager. GetClaimsAsync (TRole role)

5. Obtain the list of permissions that the user currently has:

 Task <IList <Claim> UserManager. GetClaimsAsync (TUser user)

 

 

In this way, the entire process of permission allocation can be completed. Combined with the previous permission control method, The system implements the permission control logic.

Now the question is, where does the permission list come from? Generally, after the functions of a business system are determined, the corresponding permission list is also determined. When assigning permissions to roles and assigning permissions to users, you only need to list all permissions on the page for selection, as shown below:

Save the method of the selected data call.

This problem has been solved, but new problems have emerged. If a business has many features, it will naturally lead to a lot of permissions. If you write them to the page manually, the workload will be huge, in addition, the business system may change constantly, and the permission assignment page will be constantly modified at this time. This is naturally not a good method. Next I will give you a method I want to use, not necessarily the best, but it can save a lot of trouble.

What we need to solve in the first show is how to quickly generate this permission configuration list.

The idea is to modify AuthorizeAttribute, add the permission description information based on this feature, and use the permission description information as the Policy. The following code is directly used:

[AttributeUsage (AttributeTargets. Class | AttributeTargets. Method, AllowMultiple = true, Inherited = true)]
// The class name can be changed because I manage public class ResourceAttribute as a resource using system operations: AuthorizeAttribute {private string _ resouceName; private string _ action; public ResourceAttribute (string name) {if (string. isNullOrEmpty (name) {throw new ArgumentNullException (nameof (name);} _ resouceName = name; // set the resource name to Policy name Policy = _ resouceName ;} public string GetResource () {return _ resouceName;} public string Action {get {r Eturn _ action;} set {_ action = value; if (! String. IsNullOrEmpty (value )){
// Assemble the Resource Name and operation name into Policy = _ resouceName + "-" + value ;}}}}

  

 

If the class has been defined, let's look at how to use it. Because it is a feature definition, it can be used in the Controller class or method according to the following structure:

[Resource ("organizational structure", Action = "add Department")]

Now that the basic work has been completed, there are two problems to solve:

1. The Policy is only configured with a name, but the validation rule is not defined.

2. How to obtain the list of all Permissions

 

First, let's take a look at the first question. As described in the previous article, the Policy needs to be configured through AddAuthorization in startup in advance, but now we have not done this step, so the current permission does not work. During permission verification, the framework depends on an IAuthorizationPolicyProvider to obtain specific rules based on the Policy Name. Naturally, we will think of customizing an IAuthorizationPolicyProvider implementation. The Code is as follows:

Public class ResourceAuthorizationPolicyProvider: IAuthorizationPolicyProvider {private AuthorizationOptions _ options; public ResourceAuthorizationPolicyProvider (IOptions <AuthorizationOptions> options) {if (options = null) {throw new quota (nameof (options ));} _ options = options. value;} public Task <AuthorizationPolicy> GetDefaultPolicyAsync () {return Task. fromResult (_ options. defaultPolicy);} public Task <AuthorizationPolicy> GetPolicyAsync (string policyName) {AuthorizationPolicy = _ options. getPolicy (policyName );
      // Because our policy name is actually the corresponding permission name, you can use the following logic to return the required verification rulesIf (policy = null) {string [] resourceValues = policyName. split (new char [] {'-'}, StringSplitOptions. 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 ));}}

After implementing IAuthorizationPolicyProvider, We need to register it in the ConfigureServices (IServiceCollection services) method of startup. cs. The operation is as follows:

services.TryAdd(ServiceDescriptor.Transient<IAuthorizationPolicyProvider, ResourceAuthorizationPolicyProvider>());

 

Let's take a look at the second question. We have defined the permission information on the Controller or method. The key is how to obtain the permission list from these features and use it for permission allocation in the future. Asp.net core mvc provides a class resolution mechanism, IApplicationModelProvider, which has many dependent information. I will introduce more here. In the future, I will create a series separately, this article introduces the internal mechanism of asp.net core mvc.

Directly Add code

Public class ResourceApplicationModelProvider: IApplicationModelProvider {private readonly consumer _ policyProvider; public ResourceApplicationModelProvider (IAuthorizationPolicyProvider policyProvider) {_ policyProvider = policyProvider;} public void consumer (ApplicationModelProviderContext context) {} public void OnProvidersExecuting (ApplicationModelProviderContext context) {if (context = null) {throw new ArgumentNullException (nameof (context ));} list <ResourceAttribute> attributeData = new List <ResourceAttribute> ();
// Cyclically obtain all Controllers foreach (var controllerModel in context. Result. Controllers ){
// Obtain ResourceAttribute var resourceData = controllerModel. attributes. ofType <ResourceAttribute> (). toArray (); if (resourceData. length> 0) {attributeData. addRange (resourceData);} // method of the cyclic controller foreach (var actionModel in controllerModel. actions ){
// Obtain the ResourceAttribute var actionResourceData = actionModel of the method. attributes. ofType <ResourceAttribute> (). toArray (); if (actionResourceData. length> 0) {attributeData. addRange (actionResourceData) ;}}// write all resourceattribute information to a global resourcedata. resourcedata can be used elsewhere, the definition of resourcedata is supplemented with foreach (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, all the permission information is obtained through ResourceData. Resources on the permission assignment page, and displayed directly on the page in a circular manner.

 

I finally finished writing. Haha ~~

 

  

  

  

Related Article

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.