首页 > 作文

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

更新时间:2023-04-04 12:15:14 阅读: 评论:0

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

一、角色访问控制之rbac

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

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

rbac0:是rbac的核心思想。rbac1:是把rbac樊振东许昕夺冠的角色分层模型。rbac2:增加了rbac的约束模型。rbac3:整合rbac2 + rbac1。

二、abp中的rbac

在abp中,已经集成了这些概念,并在modulezero模块中实现了这些概念,基于identityrver4的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_urs = "pages.frame.urs";    public const string pages_frame_urs_create = "pages.frame.urs.create";    public const string pages_frame_urs_update = "pages.frame.urs.update";    public const string pages_frame_urs_delete = "pages.frame.urs.delete";    public const string pages_frame_urs_retpassword = "pages.frame.urs.retpassword";    #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 tpermissions(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);        #endregio卷土重来是什么意思n        #region 组织机构        var organizationunits = frame.createchildpermission(permissionnames.pages_fram台湾偶像剧排行榜e_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 urs = frame.createchildpermission(permissionnames.pages_frame_urs, l("urs"));        urs.createchildpermission(permissionnames.pages_frame_urs_create, l("createur"));        urs.createchildpermission(permissionnames.pages_frame_urs_update, l("updateur"));        urs.createchildpermission(permissionnames.pages_frame_urs_delete, l("deleteur"));        urs.createchildpermission(permissionnames.pages_frame_urs_retpassword, l("retpassword"));        #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: "",    requiredpermissionname: permissionnames.pages_frame).additem(    new menuitemdefinition(//组织机构        pagenames.organizationunits,        l(pagenames.organizationunits),        url: "/organizationunits",        icon: "",        requiredpermissionname: permissionnames.pages_frame_organizationunits    )).additem(    new menuitemdefinition(//用户管理        pagenames.urs,        l(pagenames.urs),        url: "/urs",        icon: "",        requiredpermissionname: permissionnames.pages_frame_urs    )).additem(    new menuitemdefinition(//角色管理        pagenames.roles,        l(pagenames.roles),        url: "/roles",        icon: "",        requiredpermissionname: permissionnames.pages_frame_roles    )).additem(    new menuitemdefinition(//系统设置        pagenames.hostttings,        l(pagenames.hostttings),        url: "/hostttings",        icon: "",        requiredpermissionname: permissionnames.pages_frame_hostttings    ))

在前端页面上,对于按钮级别的控制也通过权限判定,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.tnormalizedname();    checkerrors(await _rolemanager.createasync(role));    var grantedpermissions = permissionmanager        .getallpermissions()        .where(p => input.permissionnames.contains(p.name))        .tolist();    await _rolemanager.tgrantedpermissionsasync(role, grantedpermissions);}

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

3、用户与角色

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

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

[abpauthorize(permissionnames.pages_frame_urs_create)]private async task createur(createorupdateurinput input){    var ur = objectmapper.map<ur>(input.ur);    ur.tenantid = abpssion.tenantid;    ur.imailconfirmed = true;    ur.name = "name";    ur.surname = "surname";    //ur.emailaddress = string.empty;    await urmanager.initializeoptionsasync(abpssion.tenantid);    foreach (var validator in _passwordvalidators)    {        checkerrors(await validator.validateasync(urmanager, ur, appconsts.defaultpassword));    }    ur.password = _passwordhasher.hashpassword(ur, appconsts.defaultpassword);    await _urmanager.initializeoptionsasync(abpssion.tenantid);    checkerrors(await _urmanager.createasync(ur, appconsts.defaultpassword));    if (input.assignedrolenames != null)    {        checkerrors(await _urmanager.troles(ur, input.assignedrolenames));    }    if (input.organizationunitids != null)    {        await _urmanager.torganizationunitsasync(ur, input.organizationunitids);    }    currentunitofwork.savechanges();}

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

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

仓库地址:https://gitee.com/530521314/partner.surround.git

到此这篇关于基于abp框架实现rbac(角色访问控制)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-04 12:15:12,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/62cbd31c9eb6806be1d2201f58392d50.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:基于ABP框架实现RBAC(角色访问控制).doc

本文 PDF 下载地址:基于ABP框架实现RBAC(角色访问控制).pdf

标签:权限   角色   用户   菜单
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图