【愚公系列】2022年03月 .NET架构班 014-ABP vNext 权限模块

举报
愚公搬代码 发表于 2022/03/06 01:18:06 2022/03/06
【摘要】 一、权限模块四种经典权限模型如下:自主访问控制(DAC, Discretionary Access Control)强制访问控制(MAC, Mandatory Access Control)基于角色访问控制(RBAC, Role-based Access Control)基于属性访问控制(ABAC, Attribute-based Access Control)。 1.RBACRBAC是一...

一、权限模块

四种经典权限模型如下:

  • 自主访问控制(DAC, Discretionary Access Control)
  • 强制访问控制(MAC, Mandatory Access Control)
  • 基于角色访问控制(RBAC, Role-based Access Control)
  • 基于属性访问控制(ABAC, Attribute-based Access Control)。

1.RBAC

RBAC是一套成熟的权限模型。在传统权限模型中,我们直接把权限赋予用户。而在RBAC中,增加了“角色”的概念,我们首先把权限赋予角色,再把角色赋予用户。这样,由于增加了角色,授权会更加灵活方便。在RBAC中,根据权限的复杂程度,又可分为RBAC0、RBAC1、RBAC2、RBAC3。其中,RBAC0是基础,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。我们可以根据自家产品权限的复杂程度,选取适合的权限模型。

RBAC0设计图:
在这里插入图片描述

RBAC1设计图:
在这里插入图片描述
RBAC2设计图:

RBAC2,职责分离扩展版的 RBAC,为了避免用户拥有过多权限而产生利益冲突。

职责分离有两种模式:

  • 静态职责分离(Static Separation of Duty):用户无法同时被赋予有冲突的角色。
  • 动态职责分离(Dynamic Separation of
    Duty):用户在一次会话(Session)中不能同时激活自身所拥有的、互相有冲突的角色,只能选择其一。

在这里插入图片描述
RBAC3设计图:

RBAC3,最复杂也是最全面的 RBAC 模型,它在 RBAC0 的基础上,将 RBAC1 和 RBAC2 中的优化部分进行了整合,可以认为是 RBAC0、RBAC1、RBAC2 的集大成者。
在这里插入图片描述
基于RBAC权限设计图:

首先是:用户、角色、权限。而权限,具体到某个软件来说,实际上包含两个方面:一个是菜单权限,另一个是数据权限。
在这里插入图片描述

2.ABAC

ABAC授权模型理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。从使用场景来说比较适用于用户数量多并且授权比较复杂的场景。简单的场景也是可以使用ABAC的,但是使用基础的ACL或者RBAC也能满足需求。

场景一:

还是拿上面的例子来说:P5(职级)的研发(职位)同学在公司内网(环境)可以查看和下载(操作)代码。

在需要根据环境属性和操作属性来动态计算权限的时候,使用其他的授权模型可能不太能满足需求。这个时候就需要使用ABAC授权模型。

场景二:

ABAC也适用于公司成员(角色)快速变化的场景,由于ABAC 是通过用户的属性来授权的。在新建用户/修改用户属性时会自动更改用户的权限,无需管理员手动更改账户角色。

在属性的组合比较多,需要更细粒度地划分角色的情况下。RBAC需要建立大量的角色。ABAC授权模型会更加灵活。

在这里插入图片描述

3.权限模块的源码

下载地址:

https://github.com/abpframework/abp/tree/dev/modules/PermissionManagement

二、集成权限模块

1.EBusiness.Application.Contracts集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Domain.Shared

2、然后在EBusinessDomainSharedModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementDomainSharedModule)
        )]
 public class EBusinessDomainSharedModule : AbpModule
 {}

2.EBusiness.Domain集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Domain

2、然后在EBusinessDomainModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementDomainModule)
        )]
    public class EBusinessDomainSharedModule : AbpModule

 {}

3.EBusiness.EntityFrameworkCore集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.EntityFrameworkCore

2、然后在EBusinessEntityFrameworkCoreModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementEntityFrameworkCoreModule)
        )]
    public class EBusinessEntityFrameworkCoreModule: AbpModule

 {}

3、然后在EBusinessDbContext类上实现IPermissionManagementDbContext上下文

 public DbSet<PermissionGrant> PermissionGrants { get; }

4、然后在EBusinessDbContext类上添加

 [ReplaceDbContext(typeof(IPermissionManagementDbContext))]
    [ConnectionStringName("Default")]
    public class EBusinessDbContext : 
        AbpDbContext<EBusinessDbContext>,
        IPermissionManagementDbContext
    {}

5、然后在OnModelCreating方法中添加

 protected override void OnModelCreating(ModelBuilder builder)
 {
 	base.OnModelCreating(builder);

    /* Include modules to your migration db context */
    .....          
    builder.ConfigurePermissionManagement();
    .....
 }

6、然后在YDT.EBusiness.EntityFrameworkCore生成迁移文件
使用PCM生成迁移文件

Add-Migration Created_Product_Entity -c EBusinessDbContext
 Update-Database

7、查询数据表生成了很多用户表
在这里插入图片描述

4.EBusiness.Application.Contracts集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Application.Contracts

2、然后在EBusinessApplicationContractsModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementApplicationContractsModule)
        )]
    public class EBusinessApplicationContractsModule: AbpModule

 {}

5.EBusiness.Application集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Application.Contracts

2、然后在EBusinessApplicationModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementApplicationModule)
        )]
    public class EBusinessApplicationContractsModule: AbpModule

 {}

6.EBusiness.HttpApi集成权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Application.Contracts

2、然后在EBusinessHttpApiModule文件上增加

[DependsOn(
        typeof(AbpPermissionManagementHttpApiModule)
 )]
 public class EBusinessApplicationContractsModule: AbpModule
 {}

7.EBusiness.HttpApi.Host集成权限模块

1、先进入到EBusinessHttpApiHostModule中
2、然后在类中OnApplicationInitialization方法中添加

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.AddAuthorizationCore();
}

3、然后在类中OnApplicationInitialization方法中添加

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.AddAuthorizationCore();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
     app.UseAuthorization();
}

三、使用权限模块

1、在ProductAppService类添加Authorize特性

[Authorize(EBusinessPermissions.Products.Default)]

四、定义权限模块

1.用户权限授权

1、EBusinessPermissionDefinitionProvider定义权限

public class EBusinessPermissionDefinitionProvider : PermissionDefinitionProvider
{
    public override void Define(IPermissionDefinitionContext context)
    {
        var myGroup = context.AddGroup("EBusiness");
        var permissionDefinition = myGroup.AddPermission("EBusiness.Products");
   /* permissionDefinition.AddChild(EBusinessPermissions.Products.Select);
    permissionDefinition.AddChild(EBusinessPermissions.Products.Update);
    permissionDefinition.AddChild(EBusinessPermissions.Products.Create);
    permissionDefinition.AddChild(EBusinessPermissions.Products.Delete);*/
	}
}

2、ProductAppService 接口授权

[Authorize("EBusiness.Products")]
public class ProductAppService : CrudAppService<
                                Product, 
                                ProductDto, 
                                Guid, 
                                PagedAndSortedResultRequestDto,
                                CreateProductDto, 
                                UpdateProductDto>, IProductAppService
{
}

3.IEBusinessPermissionsAppService用户授权

先创建IEBusinessPermissionsAppService接口

public interface IEBusinessPermissionsAppService
{
    public  Task AddRolePermissionAsync(string roleName, string permission);

    public  Task AddUserPermissionAsync(Guid userId, string permission);
}

在这里插入图片描述
然后创建EBusinessPermissionsAppService实现类

/// <summary>
/// 权限服务
/// </summary>
[Authorize]
public class EBusinessPermissionsAppService: EBusinessAppService,IEBusinessPermissionsAppService/*, IApplicationService, ITransientDependency*/
{
    private readonly IPermissionManager _permissionManager;

    public EBusinessPermissionsAppService(IPermissionManager permissionManager)
    {
        _permissionManager = permissionManager;
    }

    public async Task AddRolePermissionAsync(string roleName, string permission)
    {
        await _permissionManager
        .SetForRoleAsync(roleName, permission, true);
    }

    public async Task AddUserPermissionAsync(Guid userId, string permission)
    {
        await _permissionManager
        .SetForUserAsync(userId, permission, true);
    }

    public async Task AddUserEamilPermissionAsync(string Eamil, string permission)
    {
        await _permissionManager.SetAsync(permission, UserEmailPermissionValueProvider.ProviderName, Eamil,true);
    }
}

在这里插入图片描述

然后调用调用接口进行授权

2.用户子权限授权

1、先在EBusinessPermissionDefinitionProvider类中添加

public class EBusinessPermissionDefinitionProvider : PermissionDefinitionProvider
{
        public override void Define(IPermissionDefinitionContext context)
        {
     
         var myGroup = context.AddGroup("EBusiness");
         var permissionDefinition = myGroup.AddPermission("EBusiness.Products");

         permissionDefinition.AddChild("EBusiness.Products.Select");
     }
}

2、接口授权

[Authorize("EBusiness.Products")]
public class ProductAppService : CrudAppService<
                                Product, 
                                ProductDto, 
                                Guid, 
                                PagedAndSortedResultRequestDto,
                                CreateProductDto, 
                                UpdateProductDto>, IProductAppService
{
    [Authorize("EBusiness.Products.Select")]
    public void GetProductByName()
    {
        throw new NotImplementedException();
    }

}

3.用户业务字段授权

1、先在EBusinessPermissionDefinitionProvider类中添加

public class EBusinessPermissionDefinitionProvider : PermissionDefinitionProvider
{
        public override void Define(IPermissionDefinitionContext context)
        {
     
         var myGroup = context.AddGroup("EBusiness");
         var permissionDefinition = myGroup.AddPermission("EBusiness.Products");

         permissionDefinition.AddChild("EBusiness.Products.Select");
         permissionDefinition.AddChild("EBusiness.Products.Select.Price");
     }
}

2、接口授权

[Authorize("EBusiness.Products")]
public class ProductAppService : CrudAppService<
                                Product, 
                                ProductDto, 
                                Guid, 
                                PagedAndSortedResultRequestDto,
                                CreateProductDto, 
                                UpdateProductDto>, IProductAppService
{
    [Authorize("EBusiness.Products.Select")]
    public void GetProductByName()
    {
    	if (!AuthorizationService.IsGrantedAsync("", EBusinessPermissions.Products.Price).Result)
        {
             throw new AbpException("没有商品价格权限");
        }
        throw new NotImplementedException();
    }

}

4.权限复用

1、先在EBusinessPermissions类中把权限定义全部复制

public static class EBusinessPermissions
    {
        public const string GroupName = "EBusiness";
    //Add your own permission names. Example:
    public const string ProductPermission = GroupName + ".Products";
    
   public static class Products
    {
        public const string Default = GroupName + ".Products";
        public const string Select = Default + ".Select";
        public const string Create = Default + ".Create";
        public const string Update = Default + ".Update";
        public const string Delete = Default + ".Delete";
        public const string ManagePermissions = Default + ".ManagePermissions";
    }

    public static class Orders
    {
        public const string Default = GroupName + ".Orders";
        public const string Select = Default + ".Select";
        public const string Create = Default + ".Create";
        public const string Update = Default + ".Update";
        public const string Delete = Default + ".Delete";
        public const string ManagePermissions = Default + ".ManagePermissions";
    }
}

2、然后在EBusinessPermissionDefinitionProvider和商品接口中引用

3、动态配置思路如下:

 实现条件
1、特性:就是用来配置具体的权限和字段 1、具体字段 2、权限字段 [AuthorizeProduct]
1、ActionFiter:
    1.1 实现ActionFiter接口
    1.2 获取方法上面的AuthorizeProduct特性
    1.3 获取商品结果
    1.4 从特性上获取配置参数
    1.5 参数和商品接口做对比

五、权限模块原理

1.权限定义原理

接口

1、PermissionDefinition

2、PermissionDefinitionProvider

3、PermissionDefinitionManager

说明

1、PermissionDefinition执行定义

2、PermissionDefinitionProvider提供权限。

3、PermissionDefinitionManager 核心执行

2.权限授权原理

接口实现

1、PermissionManager

2、PermissionManagementProvider

3、IPermissionGrantRepository

3.权限鉴权原理

1、AuthorizationInterceptor

2、MethodInvocationAuthorizationService

3、AbpAuthorizationService

4、PermissionRequirementHandler

5、PermissionChecker

6、UserPermissionValueProvider

六、权限自定义

1.自定义权限类

1、在用户权限文件夹中创建Email字段校验类,继承PermissionManagementProvider

/// <summary>
/// UserEmail 基于用户邮件权限
/// </summary>
public class UserEmailPermissionManagementProvider : PermissionManagementProvider
{
    public UserEmailPermissionManagementProvider(IPermissionGrantRepository permissionGrantRepository, IGuidGenerator guidGenerator, ICurrentTenant currentTenant) : base(permissionGrantRepository, guidGenerator, currentTenant)
    {
    }

    public override string Name => "UE"; // 代表用户邮件
}

2、在用户权限文件夹中创建Email字段校验类,继承PermissionValueProvider

/// <summary>
/// 1、自定义权限校验
/// </summary>
class UserEmailPermissionValueProvider : PermissionValueProvider
{
    public const string ProviderName = "UE";

    public UserEmailPermissionValueProvider(IPermissionStore permissionStore) : base(permissionStore)
    {
    }

    public override string Name => ProviderName;

    public override async Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context)
    {
        // 1、从登录里面获取邮箱
        var Email = context.Principal?.FindFirst(AbpClaimTypes.Email)?.Value;

        if (Email == null)
        {
            return PermissionGrantResult.Undefined;
        }

        // 2、从权限表查询是否有权限
        return await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, Email)
            ? PermissionGrantResult.Granted
            : PermissionGrantResult.Undefined;
    }

    public override async Task<MultiplePermissionGrantResult> CheckAsync(PermissionValuesCheckContext context)
    {
        var permissionNames = context.Permissions.Select(x => x.Name).Distinct().ToArray();
        Check.NotNullOrEmpty(permissionNames, nameof(permissionNames));

        var Email = context.Principal?.FindFirst(AbpClaimTypes.Email)?.Value;
        if (Email == null)
        {
            return new MultiplePermissionGrantResult(permissionNames);
        }

        return await PermissionStore.IsGrantedAsync(permissionNames, Name, Email);
    }
}

3、配置权限类
在EBusinessApplicationModule中注册PermissionManagementProvider类

public override void ConfigureServices(ServiceConfigurationContext context)
{
    Configure<AbpAutoMapperOptions>(options =>
    {
        options.AddMaps<EBusinessApplicationModule>();
    });

    // 自定义权限校验处理
    Configure<AbpPermissionOptions>(options =>
    {
        options.ValueProviders.Add<UserEmailPermissionValueProvider>();
    });

    // 自定义权限管理
    Configure<PermissionManagementOptions>(options =>
    {
        options.ManagementProviders.Add<UserEmailPermissionManagementProvider>();
    });
}

2.使用自定义权限类

权限类中配置Email 权限字段

public static class EBusinessPermissions
{
    public const string GroupName = "EBusiness";
    // 根据领域模型来取

    //Add your own permission names. Example:
   // public const string ProductPermission = GroupName + ".Products";


    public static class Products
    {
        public const string Default = GroupName + ".Products";
        public const string Select = Default + ".Select";
        public const string Price = Select + ".Price";
        public const string Email = "EBusiness.Products.Select.admin@abp.io";
        public const string Create = Default + ".Create";
        public const string Update = Default + ".Update";
        public const string Delete = Default + ".Delete";
        public const string ManagePermissions = Default + ".ManagePermissions";
    }

    public static class Orders
    {
        public const string Default = GroupName + ".Orders";
        public const string Select = Default + ".Select";
        public const string Create = Default + ".Create";
        public const string Update = Default + ".Update";
        public const string Delete = Default + ".Delete";
        public const string ManagePermissions = Default + ".ManagePermissions";
    }
}

注册权限字段

public class EBusinessPermissionDefinitionProvider : PermissionDefinitionProvider
{
    public override void Define(IPermissionDefinitionContext context)
    {
        /*var myGroup = context.AddGroup(EBusinessPermissions.GroupName);*/
        //Define your own permissions here. Example:
        //myGroup.AddPermission(EBusinessPermissions.MyPermission1, L("Permission:MyPermission1"));

        var myGroup = context.AddGroup(EBusinessPermissions.GroupName);
        var permissionDefinition = myGroup.AddPermission(EBusinessPermissions.Products.Default);

        var permissionDefinition1 =  permissionDefinition.AddChild(EBusinessPermissions.Products.Select);
                                    permissionDefinition1.AddChild(EBusinessPermissions.Products.Price);
                                    permissionDefinition1.AddChild(EBusinessPermissions.Products.Email);

        permissionDefinition.AddChild(EBusinessPermissions.Products.Update);
        permissionDefinition.AddChild(EBusinessPermissions.Products.Create);
        permissionDefinition.AddChild(EBusinessPermissions.Products.Delete);
    }

    private static LocalizableString L(string name)
    {
        return LocalizableString.Create<EBusinessResource>(name);
    }
}

使用权限

[Authorize(EBusinessPermissions.Products.Email)]

七、权限模块其他客户端使用

1.EBusiness.Web页面访问权限模块

1、先在项目中通过Nuget下载

Volo.Abp.PermissionManagement.Web

2、然后在EBusinessApplicationModule文件上增加

[DependsOn(
	typeof(AbpPermissionManagementWebModule)
)]
 public class EBusinessWebModule: AbpModule
 {}

2.OA系统调用权限模块

1、先在项目中通过Nuget下载

YDT.EBusiness.HttpApi.Client

2、然后在YDT.OA文件上增加

 [DependsOn(
	typeof(AbpPermissionManagementHttpApiClientModule)
 )]
 public class OAModule: AbpModule
 {}

3、JavaScript添加权限
授权

abp.auth.isGranted('MyPermissionName');

鉴权

await AuthorizationService.CheckAsync("Author_Management_Create_Books");
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。