The best way to learn is to do it. Here, we will develop a common permission management system to experience and learn Asp.net Core from scratch. The overall plan of the project is roughly as follows
The previous article introduced how to control permissions, that is, when accessing a controller or method, the current user must have specific permissions, but how to allocate permissions in the program? ? The following is an introduction to how to use the Microsoft.AspNetCore.Identity.EntityFrameworkCore framework to assign permissions.
Before introducing the allocation method, we must understand the permission relationship, which involves three objects: users, roles, and permissions. Permissions are assigned to roles, and roles are assigned to users. When a user belongs to a certain After adding the role, the user will have the list of permissions included in the role. For example, there is now an information administrator role. This role includes information deletion permissions. When the user Zhang San has the information administrator role, Zhang San will have the information deletion permission. Delete permissions. In some special scenarios, permissions can also be assigned directly to users, which means that certain permissions can be assigned directly to users, bypassing roles. Such 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 of the role
IdentityUserClaim
IdentityUserRole
After understanding the basic concepts, let’s take a look at how to assign permissions.
1. Assign permissions to roles: Microsoft.AspNetCore.Identity.EntityFrameworkCore provides the RoleManager class, which provides methods for assigning permissions to roles:
Task
The first parameter represents the corresponding role object, and the second parameter represents a permission information
2. Assign permissions to the user: Microsoft.AspNetCore.Identity.EntityFrameworkCore The UserManager class is provided in the class, which provides methods for assigning permissions to users:
Task
The first parameter represents the corresponding user Object, the second parameter represents a permission information
3, assign users to roles: the same UserManager class is used, the method used:
AddToRoleAsync(TUser user, string role)
The first parameter represents the user object, and the second parameter is the name of the role.
4. Get the list of permissions currently possessed by the role:
Task
5, get the list of permissions currently possessed by the user:
Task
In this way, the entire process of permission allocation can be completed. Combined with the previous permission control method, the system can realize the complete permission control logic.
Now the question is, where does the permission list come from? Generally speaking, after a business system function is determined, the corresponding permission list is naturally determined. When assigning permissions to roles and assigning permissions to users, you only need to list all the permissions on the page for selection. Yes, the rendering is as follows:
# Just call the corresponding method to save the selected data.
This problem was solved, but a new problem came again. If a business function has too many points, it will naturally lead to a lot of permissions. If it is written completely manually on the page, the workload will naturally be very large. Furthermore, the business system may continue to change. At this time, I will also constantly modify the permission allocation page. This is naturally not a good method. Let me tell you a method I think of. It may not be the best, but it can save a lot of trouble.
The first problem we need to solve is how to quickly generate this permission configuration list.
The idea is to transform the AuthorizeAttribute, add permission description information based on this feature, and use the permission description information as Policy. Let’s go directly to the code:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited =true)] //类名称可以改,因为我把系统操作当作资源来管理 public class ResourceAttribute:AuthorizeAttribute { private string _resouceName; private string _action; public ResourceAttribute(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } _resouceName = name; //把资源名称设置成Policy名称 Policy = _resouceName; } public string GetResource() { return _resouceName; } public string Action { get { return _action; } set { _action = value; if (!string.IsNullOrEmpty(value)) { //把资源名称跟操作名称组装成Policy Policy = _resouceName + "-" + value; } } } }
The class has been defined, so let’s see how to use it. Because it is a feature definition, it can be in the controller class or The method is used according to the following structure:
[Resource("Organizational Structure", Action = "Add Department")]
The basic work has been completed here, and there are still two questions to ask. Solution:
1, Policy is only configured with a name, but the specific verification rules are not defined
2, How to obtain all permission lists
##
先来看第一个问题,前面的文章介绍了,Policy需要提前在startup里通过AddAuthorization进行配置,但是现在我们并没有做这样的步骤,所以目前权限还不会起作用。框架在权限验证的时候,会依赖一个IAuthorizationPolicyProvider来根据Policy名称获取具体的规则,自然我们会想到自定义一个IAuthorizationPolicyProvider实现,代码如下:
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(_options.DefaultPolicy); } public Task<authorizationpolicy> GetPolicyAsync(string policyName) { AuthorizationPolicy policy = _options.GetPolicy(policyName); //因为我们policy的名称其实就是对应的权限名称,所以可以用下列逻辑返回需要的验证规则 if (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)); } } </authorizationpolicy></authorizationpolicy></authorizationoptions>
实现了IAuthorizationPolicyProvider,我们就需要在startup.cs的ConfigureServices(IServiceCollection services)方法中进行注册,操作如下:
复制代码 代码如下:
services.TryAdd(ServiceDescriptor.Transient
再来看第二个问题,我们已经在控制器或者方法上定义了权限信息,关键是我们如何从这些特性里获取到权限列表,将来用于权限分配的时候使用。在asp.net core mvc中提供了一个类解析机制,IApplicationModelProvider,这个依赖信息比较多,这里就不过多介绍,后续我会单独开一个系列,介绍asp.net core mvc的内部机制。
直接上代码
public class ResourceApplicationModelProvider : IApplicationModelProvider { private readonly IAuthorizationPolicyProvider _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>(); //循环获取所有的控制器 foreach (var controllerModel in context.Result.Controllers) { //得到ResourceAttribute var resourceData = controllerModel.Attributes.OfType<resourceattribute>().ToArray(); if (resourceData.Length > 0) { attributeData.AddRange(resourceData); } //循环控制器方法 foreach (var actionModel in controllerModel.Actions) { //得到方法的ResourceAttribute var actionResourceData = actionModel.Attributes.OfType<resourceattribute>().ToArray(); if (actionResourceData.Length > 0) { attributeData.AddRange(actionResourceData); } } } //把所有的resourceattribute的信息写到一个全局的resourcedata中,resourcedata就可以在其他地方进行使用,resourcedata定义后面补充 foreach (var item in attributeData) { ResourceData.AddResource(item.GetResource(), item.Action); } } public int Order { get { return -1000 + 11; } } } </resourceattribute></resourceattribute></resourceattribute></resourceattribute>
resourcedata定义如下
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; } }
然后在startup中注册我们刚刚定义的IApplicationModelProvider:
复制代码 代码如下:
services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, ResourceApplicationModelProvider>());
然后在权限分配页面通过ResourceData.Resources就获取到了所有的权限信息,然后通过循环的方式直接显示到页面上即可。
终于写完了,哈哈~~
以上就是asp.net core项目mvc权限控制 分配权限的图文详情的内容,更多相关内容请关注PHP中文网(www.php.cn)!