我的编程空间,编程开发者的网络收藏夹
学习永远不晚

基于ABP框架实现RBAC(角色访问控制)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

基于ABP框架实现RBAC(角色访问控制)

在业务系统需求规划过程中,通常对于诸如组织机构、用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然,还有诸如多语言、设置管理、认证和授权等。对于这部分功能,ABP中存在这些概念,并且通过Module Zero模块完成了这些概念。

一、角色访问控制之RBAC

RBAC:Role Based Access Control,基于角色的访问控制,这在目前大多数软件中来讲已经算得上是普遍应用了,最常见的结构如下,结构简单,设计思路清晰。

但是也存在其它升级版的设计,诸如用户权限表、角色组、用户组的概念等,具体分类有RBAC0、RBAC1、RBAC2等,后者功能越来越强大,也越来越复杂。

  • RBAC0:是RBAC的核心思想。
  • RBAC1:是把RBAC的角色分层模型。
  • RBAC2:增加了RBAC的约束模型。
  • RBAC3:整合RBAC2 + RBAC1。

二、ABP中的RBAC

在Abp中,已经集成了这些概念,并在ModuleZero模块中实现了这些概念,基于IdentityServer4的ModuleZero模块完成了封装。对于我们大多数以业务为中心的开发人员来讲,不应该又去造一个轮子,而是应该开好这辆车。首先看下Abp中的RBAC模型

在这其中权限表中记录了用户与权限,角色与权限两部分。对于权限通常指的是功能权限和数据权限两部分,一般来讲,大多指的是功能权限,这种通过角色与权限进行管理即可,如还有用户部分的功能区分,则可以再使用上用户与权限,而对于数据权限,可以利用用户与权限部分,个人用的比较少,但是,可以想象到这么一个场景,针对于一家门店内的多个店长,角色相同即相应的权限相同,但各自关心的数据来源不同,关心东部、南部等数据,而不关心西部、北部数据,因此可以在数据层面进行划分,比如设置数据来源,东南西北,对于数据来源进行权限关联,这样一来用户本身如果拥有东部数据权限,则只能看到东部数据。

1、权限声明及应用

在Abp中,需要首先在Core层/Authorization/PermissionNames.cs中声明权限,Abp权限部分设计原则是:先声明再使用


/// <summary>
/// 权限命名
/// </summary>
public static class PermissionNames
{
    #region 顶级权限
    public const string Pages = "Pages";
    #endregion

    #region 基础支撑平台
    public const string Pages_Frame = "Pages.Frame";

    #region 租户管理
    public const string Pages_Frame_Tenants = "Pages.Frame.Tenants";
    #endregion

    #region 组织机构
    public const string Pages_Frame_OrganizationUnits = "Pages.Frame.OrganizationUnits";
    public const string Pages_Frame_OrganizationUnits_Create = "Pages.Frame.OrganizationUnits.Create";
    public const string Pages_Frame_OrganizationUnits_Update = "Pages.Frame.OrganizationUnits.Update";
    public const string Pages_Frame_OrganizationUnits_Delete = "Pages.Frame.OrganizationUnits.Delete";
    #endregion

    #region 用户管理
    public const string Pages_Frame_Users = "Pages.Frame.Users";
    public const string Pages_Frame_Users_Create = "Pages.Frame.Users.Create";
    public const string Pages_Frame_Users_Update = "Pages.Frame.Users.Update";
    public const string Pages_Frame_Users_Delete = "Pages.Frame.Users.Delete";
    public const string Pages_Frame_Users_ResetPassword = "Pages.Frame.Users.ResetPassword";
    #endregion

    #region 角色管理
    public const string Pages_Frame_Roles = "Pages.Roles";
    public const string Pages_Frame_Roles_Create = "Pages.Frame.Roles.Create";
    public const string Pages_Frame_Roles_Update = "Pages.Frame.Roles.Update";
    public const string Pages_Frame_Roles_Delete = "Pages.Frame.Roles.Delete";
    #endregion

}

然后在Core层/Authorization/XXXAuthorizationProvider.cs中设置具体权限,在此处设置权限时,可以根据权限设计时候的职责划分,比如如果仅仅是多租户需要这部分,那便设置权限范围为多租户即可。


public class SurroundAuthorizationProvider : AuthorizationProvider
{
    public override void SetPermissions(IPermissionDefinitionContext context)
    {
        #region 顶级权限
        var pages = context.CreatePermission(PermissionNames.Pages, L("Pages"));
        #endregion

        #region 基础支撑平台
        var frame = pages.CreateChildPermission(PermissionNames.Pages_Frame, L("Frame"));

        #region 租户管理
        frame.CreateChildPermission(PermissionNames.Pages_Frame_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
        #endregion

        #region 组织机构
        var organizationUnits = frame.CreateChildPermission(PermissionNames.Pages_Frame_OrganizationUnits, L("OrganizationUnits"));
        organizationUnits.CreateChildPermission(PermissionNames.Pages_Frame_OrganizationUnits_Create, L("CreateOrganizationUnit"));
        organizationUnits.CreateChildPermission(PermissionNames.Pages_Frame_OrganizationUnits_Update, L("EditOrganizationUnit"));
        organizationUnits.CreateChildPermission(PermissionNames.Pages_Frame_OrganizationUnits_Delete, L("DeleteOrganizationUnit"));
        #endregion

        #region 用户管理
        var users = frame.CreateChildPermission(PermissionNames.Pages_Frame_Users, L("Users"));
        users.CreateChildPermission(PermissionNames.Pages_Frame_Users_Create, L("CreateUser"));
        users.CreateChildPermission(PermissionNames.Pages_Frame_Users_Update, L("UpdateUser"));
        users.CreateChildPermission(PermissionNames.Pages_Frame_Users_Delete, L("DeleteUser"));
        users.CreateChildPermission(PermissionNames.Pages_Frame_Users_ResetPassword, L("ResetPassword"));
        #endregion

        #region 角色管理
        var roles = frame.CreateChildPermission(PermissionNames.Pages_Frame_Roles, L("Roles"));
        roles.CreateChildPermission(PermissionNames.Pages_Frame_Roles_Create, L("CreateRole"));
        roles.CreateChildPermission(PermissionNames.Pages_Frame_Roles_Update, L("UpdateRole"));
        roles.CreateChildPermission(PermissionNames.Pages_Frame_Roles_Delete, L("DeleteRole"));
        #endregion
    }
}

在设置完毕后,需要将该类集成到Core层/XXXCoreModule当前模块中,才能使得该部分权限设置生效。


//配置权限管理
Configuration.Authorization.Providers.Add<SurroundAuthorizationProvider>();

作为业务的入口,菜单是较为直观的体现方式,现在可以,为菜单分配权限了,拥有权限的人才能看的到菜单,同时后台方法中也要有权限判定,菜单仅作为前端入口上的控制,权限判定作为后端的控制。在MVC层的Startup/XXXNavigationProvider.cs中完成菜单的配置工作,可以配置多级菜单,每个菜单可以配置相应的权限,在生成菜单判定时,如果父级菜单权限不足,则直接会跳过子级菜单的判定。


new MenuItemDefinition(//基础支撑
    PageNames.FrameManage,
    L(PageNames.FrameManage),
    icon: "&#xe828;",
    requiredPermissionName: PermissionNames.Pages_Frame
).AddItem(
    new MenuItemDefinition(//组织机构
        PageNames.OrganizationUnits,
        L(PageNames.OrganizationUnits),
        url: "/OrganizationUnits",
        icon: "&#xe6cb;",
        requiredPermissionName: PermissionNames.Pages_Frame_OrganizationUnits
    )
).AddItem(
    new MenuItemDefinition(//用户管理
        PageNames.Users,
        L(PageNames.Users),
        url: "/Users",
        icon: "&#xe6cb;",
        requiredPermissionName: PermissionNames.Pages_Frame_Users
    )
).AddItem(
    new MenuItemDefinition(//角色管理
        PageNames.Roles,
        L(PageNames.Roles),
        url: "/Roles",
        icon: "&#xe6cb;",
        requiredPermissionName: PermissionNames.Pages_Frame_Roles
    )
).AddItem(
    new MenuItemDefinition(//系统设置
        PageNames.HostSettings,
        L(PageNames.HostSettings),
        url: "/HostSettings",
        icon: "&#xe6cb;",
        requiredPermissionName: PermissionNames.Pages_Frame_HostSettings
    )
)

在前端页面上,对于按钮级别的控制也通过权限判定,Abp提供了判定方法,利用Razor语法进行按钮控制


@if (await PermissionChecker.IsGrantedAsync(PermissionNames.Pages_Core_DataDictionary_Create))
{
    <button class="layui-btn layuiadmin-btn-dataDictionary" data-type="addDataDictionary">添加类型</button>
}

在后端方法上,通常我喜欢直接在应用服务中的方法上做权限判定(当然也可以前移到MVC层,但是这样一来,针对于WebApi形式的Host层,又得多加一次判定了),利用AbpAuthorize特性,判定该方法需要哪几个权限才能访问,而在mvc的控制器上做访问认证。


[AbpAuthorize(PermissionNames.Pages_Core_DataDictionary_Create)]
private async Task CreateDataDictionaryAsync(CreateOrUpdateDataDictionaryInput input)
{

}

2、角色与权限

在Abp中,角色信息存储在abprole表中,角色与权限间的关联存储在abppermission这张表中,一个角色有多个权限,如果某个角色的权限被去掉了,这张表中的相关记录将由abp负责删除,我们只需要完成掌控哪些权限是这个角色有的就行。Abp中已经完成了角色的所有操作,但是前端部分采用的是bootstrap弄的,将其改造一波,成为layui风格。

在创建角色中,主要是将选中的权限挂钩到具体的某个角色上,该部分代码沿用abp中自带的角色权限处理方法。


private async Task CreateRole(CreateOrUpdateRoleInput input)
{
    var role = ObjectMapper.Map<Role>(input.Role);
    role.SetNormalizedName();

    CheckErrors(await _roleManager.CreateAsync(role));

    var grantedPermissions = PermissionManager
        .GetAllPermissions()
        .Where(p => input.PermissionNames.Contains(p.Name))
        .ToList();

    await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions);
}

指定角色Id,租户Id及之前声明的权限名称,在abppermission中可查看到具体角色权限。

3、用户与角色

一个用户可以承担多个角色,履行不同角色的义务,作为一个业务系统最基本的单元,abp中提供了这些概念并在Module Zero模块中已经完成了对用户的一系列操作,用户信息存储在AbpUsers表中,用户直接关联的角色保存在AbpUserRoles表中,abp中MVC版本采用的是bootstrap风格,因此,用layui风格完成一次替换,并且,改动一些页面布局。

Abp版本中,由于是土耳其大佬所开发的习惯,针对于姓和名做了拆分,因此对于我们的使用要做一次处理,我这先简单处理了一下,并且在业务系统中,邮箱时有时无,因此也需要进行考虑。


[AbpAuthorize(PermissionNames.Pages_Frame_Users_Create)]
private async Task CreateUser(CreateOrUpdateUserInput input)
{
    var user = ObjectMapper.Map<User>(input.User);
    user.TenantId = AbpSession.TenantId;
    user.IsEmailConfirmed = true;
    user.Name = "Name";
    user.Surname = "Surname";
    //user.EmailAddress = string.Empty;

    await UserManager.InitializeOptionsAsync(AbpSession.TenantId);
    foreach (var validator in _passwordValidators)
    {
        CheckErrors(await validator.ValidateAsync(UserManager, user, AppConsts.DefaultPassword));
    }

    user.Password = _passwordHasher.HashPassword(user, AppConsts.DefaultPassword);

    await _userManager.InitializeOptionsAsync(AbpSession.TenantId);

    CheckErrors(await _userManager.CreateAsync(user, AppConsts.DefaultPassword));

    if (input.AssignedRoleNames != null)
    {
        CheckErrors(await _userManager.SetRoles(user, input.AssignedRoleNames));
    }

    if (input.OrganizationUnitIds != null)
    {
        await _userManager.SetOrganizationUnitsAsync(user, input.OrganizationUnitIds);
    }

    CurrentUnitOfWork.SaveChanges();
}

此处对用户个人单独的权限没有去做处理,依照Abp的文档有那么一句话,大多数应用程序中,基于角色的已经足够使用了,如果想声明特定权限给用户,那么针对于用户本身的角色权限则被覆盖。

至此,修改整合用户、角色和权限加入到系统中初步完成了,至于一些更为丰富的功能,待逐步加入中,车子再好,司机也得睡觉。

仓库地址:https://gitee.com/530521314/Partner.Surround.git

到此这篇关于基于ABP框架实现RBAC(角色访问控制)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

基于ABP框架实现RBAC(角色访问控制)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringSecurity实现基于角色的访问控制框架

SpringSecurity是一个功能强大的安全框架,提供了基于角色的访问控制、身份验证、授权等安全功能,可轻松保护Web应用程序的安全,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-05-17

kubernetes中如何实现RBAC 角色访问控制

小编给大家分享一下kubernetes中如何实现RBAC 角色访问控制,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一:RBAC体系结构二:RBAC角色绑定流程三:说明1.RBAC的优势a.对集群中的资源和非资源权限均有完
2023-06-04

基于角色的权限控制模型RBAC实例分析

本篇内容主要讲解“基于角色的权限控制模型RBAC实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于角色的权限控制模型RBAC实例分析”吧!一、RBAC权限模型简介RBAC权限模型(Rol
2023-06-29

Spring Security基于注解的接口角色访问控制怎么实现

本文小编为大家详细介绍“Spring Security基于注解的接口角色访问控制怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring Security基于注解的接口角色访问控制怎么实现”文章能帮助大家解决疑惑,下面跟着小编的
2023-06-16

Apache如何实现基于IP的访问控制

Apache可以通过使用mod_authz_host模块来实现基于IP的访问控制。您可以通过编辑Apache的配置文件来配置基于IP的访问控制规则。以下是一个示例配置,只允许特定IP地址范围内的用户访问您的网站:
Apache如何实现基于IP的访问控制
2024-07-05

Apache如何实现基于组的访问控制

Apache可以通过使用基于组的访问控制模块来实现基于组的访问控制。其中,最常用的模块是mod_authz_groupfile模块和mod_authz_dbd模块。mod_authz_groupfile模块允许管理员使用一个简单的文本文件来
Apache如何实现基于组的访问控制
2024-07-05

Apache如何实现基于用户名的访问控制

Apache可以通过使用htpasswd文件和.htaccess文件来实现基于用户名的访问控制。创建htpasswd文件:首先要创建一个包含用户名和密码的htpasswd文件。可以使用htpasswd命令行工具来创建该文件。例如,运行以下命
Apache如何实现基于用户名的访问控制
2024-07-05

给数字人生成加上界面,基于ER-NeRF/RAD-NeRF/AD-NeRF,Gradio框架构建WEBUI,使用HLS流媒体,实现边推理边播放——之一:在WEBUI中实时输出服务器控制台日志

前言 目前数字人实现技术众多,我这里采用基于ER-NeRF,在这里可以看到其介绍:ICCV 2023 | ER-NeRF: 用于合成高保真Talking Portrait的高效区域感知神经辐射场-https://zhuanlan.zhihu
给数字人生成加上界面,基于ER-NeRF/RAD-NeRF/AD-NeRF,Gradio框架构建WEBUI,使用HLS流媒体,实现边推理边播放——之一:在WEBUI中实时输出服务器控制台日志
2023-12-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录