天天看点

.Net Core实战之基于角色的访问控制的设计

  上个月,我写了两篇微服务的文章:《.Net微服务实战之技术架构分层篇》与《.Net微服务实战之技术选型篇》,微服务系列原有三篇,当我憋第三篇的内容时候一直没有灵感,因此先打算放一放。

  本篇文章与源码原本打算实在去年的时候完成并发布的,然而我一直忙于公司项目的微服务的实施,所以该篇文章一拖再拖。如今我花了点时间整理了下代码,并以此篇文章描述整个实现思路,并开放了源码给予需要的人一些参考。

  源码:https://github.com/SkyChenSky/Sikiro.RBAC

  Role-Based Access Contro翻译成中文就是基于角色的访问控制,文章以下我都用他的简称RBAC来描述。

  现信息系统的权限控制大多数采取RBAC的思想进行实现,其本质思想是对系统各种的操作权限不是直接授予具体的某个用户,而是在用户集合与权限集合之间建立一个角色,作为间接关联。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。

  通过以上的描述,我们可以分析出以下信息:

  用户与权限是通过角色间接关联的

  角色的本质就是权限组(权限集合)

  这样做的好处在于,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理,减少系统的开销。

  

.Net Core实战之基于角色的访问控制的设计

从权限的作用可以分为三种,功能权限、访问权限、数据权限:

功能权限

功能权限指系统用户允许在页面进行按钮操作的权限。如果有权限则功能按钮展示,否则隐藏。

访问权限

访问权限指系统用户通过点击按钮后进行地址的请求访问的权限(地址跳转与接口请求),如果无权限访问,则由页面提示无权限访问。

数据权限

数据权限指用户可访问系统的数据权限,不同的用户可以访问不同的数据粒度。

数据权限的实现可大可小,大可大到对条件进行动态配置,小可小到只针对某个维度进行硬编码。不纳入这次的讨论范围。

.Net Core实战之基于角色的访问控制的设计

  时效性,直接影响到安全性,既然是权限控制,那么理应一修改权限后就立刻生效。曾经有同行问过我,是不是每一个请求都得去查一次数据库是否满足权限,如果是,数据库压力岂不是很大?

  安全性,每一个页面跳转,每一个读写请求都的进行一次权限验证,不满足的权限的功能按钮就不需要渲染,避免样式display:none的情况。

  开发效率,权限控制理应是框架层面的,因此尽可能作为非业务的侵入性,让开发人员保持原有的数据善增改查与页面渲染。

  学习门槛极低,开箱即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到 API 的每一处细节都经过精心雕琢,非常适合界面的快速开发,它更多是为服务端程序员量身定做,无需涉足各种前端工具的复杂配置,只需面对浏览器本身,让一切你所需要的元素与交互,从这里信手拈来。作为国人的开源项目,完整的接口文档与Demo示例让入门者非常友好的上手,开箱即用的Api让学习成本尽可能的低,其易用性成为快速开发框架的基础。

  主要两大优势,无模式与横向扩展。对于权限模块来说,无需SQL来写复杂查询和报表,也不需要使用到多表的强事务,上面提到的时效性的数据库压力问题也可以通过分片解决。无模式使得开发人员无需预定义存储结构,结合MongoDB官方提供的驱动可以做到快速的开发。

.Net Core实战之基于角色的访问控制的设计

  一个管理员可以拥有多个角色,因此管理员与角色是一对多的关联;角色作为权限组的存在,又可以选择多个功能权限值与菜单,所以角色与菜单、功能权限值也是一对多的关系。

.Net Core实战之基于角色的访问控制的设计

Deparment与Position属于非核心,可以按照自己的实际业务进行扩展。

  随着业务发展,需求功能是千奇百怪的,根本无法抽象出来,那么功能按钮就要随着业务进行定义。在我的项目里使用了枚举值进行定义每个功能权限,通过自定义的PermissionAttribute与响应的action进行绑定,在系统启动时,通过反射把功能权限的枚举值与相应的controller、action映射到MenuAction表,枚举值对应code字段,controller与action拼接后对应url字段。

  已初始化到数据库的权限值可以到菜单页把相对应的菜单与权限通过用户界面关联起来。

.Net Core实战之基于角色的访问控制的设计

  当所有权限关系关联上后,用户访问系统时,需要对其所有操作进行拦截与实时的权限判断,我们注册一个全局的GlobalAuthorizeAttribute,其主要拦截所有已经标识PermissionAttribute的action,查询该用户所关联所有角色的权限是否满足允许通过。

  我的实现有个细节,给判断用户IsSuper==true,也就是超级管理员,如果是超级管理员则绕过所有判断,可能有人会问为什么不在角色添加一个名叫超级管理员进行判断,因为名称是不可控的,在代码逻辑里并不知道用户起的所谓的超级管理员,就是我们需要绕过验证的超级管理员,假如他叫无敌管理员呢?

  在权限验证通过后,返回view之前,还是利用了Filter进行一个实时的权限查询,主要把该用户所拥有功能权限值查询出来通过ViewData["PermCodes"]传到页面,然后通过razor进行按钮的渲染判断。

  然而我在项目中封装了大部分常用的LayUI控件,主要利用.Net Core的TagHelper进行了封装,TagHelper内部与ViewData["PermCodes"]进行判断是否输出HTML。

.Net Core实战之基于角色的访问控制的设计

  以上就是我本篇分享的内容,项目是以单体应用提供的,方案思路也适用于前后端分离。最后附上几个系统效果图

.Net Core实战之基于角色的访问控制的设计
.Net Core实战之基于角色的访问控制的设计
.Net Core实战之基于角色的访问控制的设计

作  者:

陈珙

出  处:http://www.cnblogs.com/skychen1218/

关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教!

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!