搜索
首页后端开发C#.Net教程asp.net core项目mvc权限控制 分配权限的图文详情

学习的最好方法就是动手去做,这里以开发一个普通的权限管理系统的方式来从零体验和学习Asp.net Core。项目的整体规划大致如下

前面的文章介绍了如何进行权限控制,即访问控制器或者方法的时候,要求当前用户必须具备特定的权限,但是如何在程序中进行权限的分配呢?下面就介绍下如何利用Microsoft.AspNetCore.Identity.EntityFrameworkCore框架进行权限分配。

在介绍分配方法之前,我们必须理解权限关系,这里面涉及到三个对象:用户,角色,权限,权限分配到角色,角色再分配到用户,当某个用户属于某个角色后,这个用户就具有了角色所包含的权限列表,比如现在有一个信息管理员角色,这个角色包含了信息删除权限,当张三这个用户具有信息管理员角色后,张三就具备了信息删除的权限。在某些特殊场景下,权限也可以直接分配到用户,也就是说可以直接把某些特定的权限,绕过角色,直接分配给用户。Microsoft.AspNetCore.Identity.EntityFrameworkCore框架中都提供了这样的支持。

先把框架中主要的业务对象类介绍一下:

IdentityUser:表示一个用户信息

IdentityRole:表示一个角色信息

IdentityRoleClaim7c013bef549e108856916cfbe0707d60:表示角色具有的权限

IdentityUserClaim7c013bef549e108856916cfbe0707d60:表示用户具有的权限

IdentityUserRole7c013bef549e108856916cfbe0707d60:表示用户角色关系


基本概念理解后,下面我们就来看一下如何进行权限分配。

1,分配权限到角色:Microsoft.AspNetCore.Identity.EntityFrameworkCore中提供了RoleManager类,类中提供了把权限分配到角色的方法:

  Task9b1f9e47eb1620cf27a98765de10fb89 AddClaimAsync(TRole role, Claim claim)

  第一个参数表示对应的角色对象,第二个参数表示一个权限信息

2,分配权限到用户:Microsoft.AspNetCore.Identity.EntityFrameworkCore中提供了UserManager类,类中提供了把权限分配到用户的方法:

  Task9b1f9e47eb1620cf27a98765de10fb89 AddClaimAsync(TUser user, Claim claim)

  第一个参数表示对应的用户对象,第二个参数表示一个权限信息

3,分配用户到角色:用到的同样是UserManager类,使用的方法:

  AddToRoleAsync(TUser user, string role)

  第一个参数表示的是用户对象,第二个是角色的名称

4,获取角色当前具有的权限列表:

 Taskfebce605adaafd9dd572348f5a5bf2a8> RoleManager.GetClaimsAsync(TRole role)

5,获取用户当前具有的权限列表:

 Taskfebce605adaafd9dd572348f5a5bf2a8> UserManager.GetClaimsAsync(TUser user)

通过这样的方式就可以完成权限分配全过程,再结合前面的权限控制方法,系统就实现了完成的权限控制逻辑。

那现在的问题来了,权限列表从什么地方来?一般来说,一个业务系统功能确定后,对应的权限列表也自然就确定了,再实现分配权限到角色,分配权限到用户的功能时,只需要在页面上把所有的权限列出来进行选择即可,效果图如下:

把选择的数据调用对应的方法保存即可。

这个问题解决了,但是新的问题又来了。如果说一个业务功能点特别多,自然会导致权限也会很多,如果完全通过手工的方式写到页面上,那自然工作量会很大很大,再者业务系统可能会不断地变化,这个时候也会去不断地修改权限分配页面,这自然不是一个好的方法,下面我给大家说一个我想的一个方法,不一定是最好的,但是能省很大的事。

首秀我们需要解决的问题是,如何快速生成这个权限配置列表。

思路就是改造AuthorizeAttribute,在这个特性基础上增加权限描述信息,用权限描述信息作为Policy。下面直接上代码:

[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;
        }
      }
    }
  }

类已经定义好了,那我们就看看如何使用,因为是特性定义,所以可以在控制器类或者方法上按照下面结构使用:

[Resource("组织架构", Action = "添加部门")]

到这里基础工作已经做完,下面还有两个问题需要解决:

1,Policy现在只是配置了名称,但是具体验证规则没有定义

2,如何获取所有的权限列表


先来看第一个问题,前面的文章介绍了,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[] { &#39;-&#39; }, 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.Transientd35cc227e13486608ede2963927abb51());

再来看第二个问题,我们已经在控制器或者方法上定义了权限信息,关键是我们如何从这些特性里获取到权限列表,将来用于权限分配的时候使用。在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)!


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
掌握C#.NET设计模式:从单胎到依赖注入掌握C#.NET设计模式:从单胎到依赖注入May 09, 2025 am 12:15 AM

C#.NET中的设计模式包括Singleton模式和依赖注入。1.Singleton模式确保类只有一个实例,适用于需要全局访问点的场景,但需注意线程安全和滥用问题。2.依赖注入通过注入依赖提高代码灵活性和可测试性,常用于构造函数注入,但需避免过度使用导致复杂度增加。

现代世界中的C#.NET:应用和行业现代世界中的C#.NET:应用和行业May 08, 2025 am 12:08 AM

C#.NET在现代世界中广泛应用于游戏开发、金融服务、物联网和云计算等领域。1)在游戏开发中,通过Unity引擎使用C#进行编程。2)金融服务领域,C#.NET用于开发高性能的交易系统和数据分析工具。3)物联网和云计算方面,C#.NET通过Azure服务提供支持,开发设备控制逻辑和数据处理。

C#.NET开发人员社区:资源和支持C#.NET开发人员社区:资源和支持May 06, 2025 am 12:11 AM

C#.NET开发者社区提供了丰富的资源和支持,包括:1.微软的官方文档,2.社区论坛如StackOverflow和Reddit,3.GitHub上的开源项目,这些资源帮助开发者从基础学习到高级应用,提升编程技能。

C#.NET优势:功能,好处和用例C#.NET优势:功能,好处和用例May 05, 2025 am 12:01 AM

C#.NET的优势包括:1)语言特性,如异步编程简化了开发;2)性能与可靠性,通过JIT编译和垃圾回收机制提升效率;3)跨平台支持,.NETCore扩展了应用场景;4)实际应用广泛,从Web到桌面和游戏开发都有出色表现。

C#总是与.NET关联吗?探索替代方案C#总是与.NET关联吗?探索替代方案May 04, 2025 am 12:06 AM

C#并不总是与.NET捆绑在一起。1)C#可以在Mono运行时环境中运行,适用于Linux和macOS。2)在Unity游戏引擎中,C#用于脚本编写,不依赖.NET框架。3)C#还可用于嵌入式系统开发,如.NETMicroFramework。

.NET生态系统:C#的角色和超越.NET生态系统:C#的角色和超越May 03, 2025 am 12:04 AM

C#在.NET生态系统中扮演核心角色,是开发者的首选语言。1)C#提供高效、易用的编程方式,结合C、C 和Java的优点。2)通过.NET运行时(CLR)执行,确保跨平台高效运行。3)C#支持从基本到高级的用法,如LINQ和异步编程。4)优化和最佳实践包括使用StringBuilder和异步编程,提高性能和可维护性。

C#作为.NET语言:生态系统的基础C#作为.NET语言:生态系统的基础May 02, 2025 am 12:01 AM

C#是微软在2000年发布的编程语言,旨在结合C 的强大功能和Java的简洁性。1.C#是一种类型安全、面向对象的编程语言,支持封装、继承和多态。2.C#的编译过程将代码转化为中间语言(IL),然后在.NET运行时环境(CLR)中即时编译成机器码执行。3.C#的基本用法包括变量声明、控制流和函数定义,而高级用法涵盖异步编程、LINQ和委托等。4.常见错误包括类型不匹配和空引用异常,可通过调试器、异常处理和日志记录来调试。5.性能优化建议包括使用LINQ、异步编程和提高代码可读性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!