基于EntityFramework的权限的配置和验证
1. 概要
本文主要介绍公司现有系统框架的权限体系,和一些待扩展功能的说明。目前该权限体系基于角色构建(RBAC),原则上,系统中不允许出现对用户、组织等其他对象指派权限的情况。
2. 权限分类
目前系统中的所有表现形式的权限可以归为两类:
一类是描述对象或动作是否可见,我们称之为功能权限(Authority)。例如,菜单的可见性、用户添加按钮是否可见、用户添加方法是否可用等;
另一类是描述可见对象的范围或动作的影响范围,我们称之为数据权限(Permission)。例如,未成年用户列表、行政区域内数据操作限制等。
说明,这里authority和permission并不是取英文原意,只是用于程序简化权限对象命名,实际对应的应该是Function Permission 和 Data Permission。
2.1. 功能权限
功能权限的定义通常都可以序列化存入数据库。因此,在设计数据库表时,它和用户、角色的关系是这样的:
权限和角色、角色和用户都是多对多的关系,需要建立中间表来存储。
2.2. 数据权限
数据权限的定义大多数情况下难以序列化存入数据库。因此,在设计数据库表时,只需要记录它和角色的关系即可:
3. 实现过程
从用户的角度来说,他们只关心系统配置好之后是否符合实际业务逻辑,少数用户会主动参与到配置过程。
3.1. 配置
配置主要做了两件事情,一是定义权限,二是授权。
功能权限和数据权限的授权并没有什么区别,从数据表来看,可以简单的理解为对Role2Authority和Role2Permission表的数据改动;从界面上来看,如图
菜单权限是功能权限的一种表现形式。
3.1.1. 功能权限的定义
而定义则有较大的不同,功能权限可以在没有确定管理对象的情况进行定义,而且从实际的情况来看,系统的功能或界面设定并不完全和系统管理对象一一对应,功能权限更多的情况是对系统需求的描述。
例如,我们计划在系统中增加工程对象管理功能,这时可以快速在Authorities表中加入一个菜单权限,用于控制用户是否可以访问工程对象管理页面project.html,而此时,project.html页面可能还未开发完成,但并不影响权限的定义。另一方面,该权限定义的动作中涉及的对象可能不止工程对象,而是由多个对象操作结合完成的操作;因此,功能权限的定义应该尽量按照用户需求最小单元来划分。
3.1.2. 数据权限的定义
动态定义
数据权限的定义,目前只实现了预定义,即编码阶段的定义。数据权限授权界面所看到的可选项均为编码预设的内容。
如果想要在运行时,动态定义数据权限,例如,项目权限中的部门项目,它的定义内容为当前登录用户可以查看本部门的项目,这是对项目对象的一个范围限制。使用SQL语句,可以描述为
SELECT * FROM Projects WHERE OrgId=(SELECT OrgId FROM Users WHERE Id=@UserId)
这里可以在数据库中建立一个Permissions表,将上面这条SQL语句的条件部分命名为部门项目,并给定编号3002,存入表中;然后建立Permissions表和Role2Permissions表的外键关系实现数据权限的动态配置化,但具体操作下来,会发现很多问题。
首先,联表查询时,条件语法是有变化的;其次,动态配置需要有配置界面,在界面上录入SQL语句是不安全的,而且用户很可能并不了解SQL语法;在一些管理权限框架中,也有使用条件表达式生成器简化定义过程,这是可以尝试的方向。
而本文描述的系统中,数据层采用的是EntityFramework框架,因此无法使用SQL语法来实现动态定义数据权限。或许在对lambda表达式有了足够了解后,可以尝试通过文本建立lambda表达式,从而实现动态定义数据权限。
预定义
对于部门项目权限系统采用的是lambda描述
Formula = oper => (pro => pro.Organizations.Contains(oper.Organization));
其中oper为用户参数,pro为项目参数。数据权限的预定义内容存放在类中,并为此建立新的类库项目,称为权限库。当系统需要新的数据权限时,可以只修改权限库,生成部署文件,替换运行时环境中的部分文件达到数据权限配置化的目的。
上述表达式Formula只是数据权限对象的一个属性。数据权限名称可以定义为部门项目,编号为3002,这样可以和Role2Permissions表中的PermissionId对应起来,实现对角色的授权。
3.2. 验证
3.2.1. 功能权限的验证
对于本文描述的B/S系统,功能权限的验证可分为服务端和客户端两个不同实现。
首先,服务端的实现需要拦截所有请求,并根据会话中用户的角色、请求的资源,逐一匹配权限定义规则,实现验证。
例如,所有Handler接口都继承自一个父类,并在父类中进行验证。
客户端的实现则是隐藏用户没有权限的菜单或按钮。对于使用后台脚本语言的页面,可以使用用户角色下的权限集合很方便的进行控制;而纯html前段,则可以考虑首先隐藏所有涉及权限的元素,再通过ajax获取权限集合,显示可以访问的元素。
需要注意的是,服务端验证是必须要实现,以保证权限系统的可靠性。
3.2.2. 数据权限的验证
与功能权限不同的是,数据权限主要是对数据范围的控制;因此,验证过程最终会在系统数据层实现。这里有两种实现方式:一是只读验证,另一种是读写验证,各自有优缺点。
只读验证的方式如下面这个方法:
这是一个API查询方法,其中condition、verCondtion、attCondition是针对三个对象的数据权限,通过这个查询方法,用户将只能得到他可以查看的Project对象及子对象数据。
类似的,分页查询、视图查询等查询方法,除了用户输入的条件,还需加入PermissionManager提供的数据权限条件,最终交给业务层查询。这种方式的缺点在于,用户可能使用查询权限以外的数据,伪造修改和删除操作。
读写验证除了查询方法需要添加额外权限条件,修改和删除也要先进行数据可读性查询验证。因此,相对而言,读写验证的安全性是最高的,但性能则要比只读查询差很多。
3.2.3. 一些细节
条件的合并,PredicateBuilder是专门用于lambda条件表达式合并的工具。通常数据权限条件和用户查询条件应该使用And操作。
集中管理数据权限的验证,上述在API方法中使用PermissionManager获取数据权限条件的方式是有一些缺点的,例如,这要求所有编码人员都了解权限验证的过程,也有遗漏的可能导致数据操作不受控制。对于使用EF框架的系统,可以考虑在DbContext中集成权限验证过程。
具体的验证过程,创建一个通用的验证方法,使用当前用户作为参数,返回相关对象的过滤条件。由于数据权限是建立在对象基础上的,因此该验证方法最好使用泛型。方法将分析用户的所有角色,以及每个角色下的数据权限授权编号,并根据授权编号从预定义库中取出所有相关lambda表达进行Or或者And组合。组合方式取决于多角色权限重合的处理策略。
4. 遗留问题
最后,本文虽然到此,但基于EF框架的权限开发还有一些问题尚未解决。例如,动态定义数据权限,权限读写验证的效率问题,数据权限的集中验证等,希望自己有时间继续完善。
本文仅在博客园发布,转载请注明出处。
基于EntityFramework的权限的配置和验证的更多相关文章
- 基于思科模拟器的AAA配置与验证
拓扑图: 地址表如图所示 三个路由器之间采用ospf协议达到互通 先做ping通测试 由ApingB 由ApingC 配置AAA认证 在R1上 R1(config)#username shuaiqiy ...
- Forms身份验证和基于Role的权限验证
Forms身份验证和基于Role的权限验证 从Membership到SimpleMembership再到ASP.NET Identity,ASP.NET每一次更换身份验证的组件,都让我更失望.Memb ...
- webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制
webapi框架搭建系列博客 在上一篇的webapi框架搭建-安全机制(三)-简单的基于角色的权限控制,某个角色拥有哪些接口的权限是用硬编码的方式写在接口上的,如RBAuthorize(Roles = ...
- SVN版本库(访问权限)配置实例笔记
http://blog.csdn.net/zjianbo/article/details/8578297 SVN版本库(访问权限)配置实例笔记 本系列文章由ex_net(张建波)编写,转载请注明出处. ...
- asp.net权限控制配置web.config
项目下 有三个文件夹 A,B,C 验正方式是 Forms 验正 我要设置他们的访问权限为, A,匿名可访问 B,普通用户授权后才能访问 C,只允许管理员访问 <configuration> ...
- 【shiro】(5)---基于Shiro的权限管理
基于Shiro的权限管理项目搭建 前面写了四篇有关权限的文章,算是这篇文章的铺垫了.这篇文章采用 开发环境 JDK1.8 Eclipse Mav ...
- 【shiro】(2)---基于RUL的权限管理
基于RUL的权限管理 我想在写shiro权限管理认证前,先来一个基于URL实现的权限管理控制. 一.基于URI的权限业务逻辑 实现思路: 将系统操作的每个url配置在权限表中,将权限对应 ...
- webapi框架搭建-安全机制(三)-简单的基于角色的权限控制
webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...
- SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建
SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...
随机推荐
- 【转】#ifdef _DEBUG用法小结
原文地址:http://blog.csdn.net/shijizhisheng/article/details/1908054 1 #ifdef _DEBUG virtual void AssertV ...
- JavaScript 关于变量作用域的一道面试题
ShineJaie 原创,转载请注明出处. 昨晚在一个交流群里看到有位网友提了一个他的面试题求助答疑.刚好我也有看到,就对这个问题思考了一下,觉得这道题对理解 JavaScript 作用域还是很有帮助 ...
- MySQL中表格各页面的注意和操作项
- Mac上安装 mySql
今天在mac系统上安装了 mySql 和大家分享下 安装的过程.. 首先 第一步 需要在oracle的网站下载 mysql 的mac 版本. 下载地址如下: http://www.mysql.com/ ...
- 【BZOJ】【1027】【JSOI2007】合金
计算几何/凸包/Floyd Orz rausen大爷太强辣 计算几何题目果然不会做>_> 这个题……虽然他给了3个坐标,但实际上是个二维的计算几何题= =因为第三维坐标可以直接用前两维坐标 ...
- Word2007插入两种页码
做毕设,摘要,Abstract,目录,第一章,现在想要“摘要,Abstract,目录”编页码“为罗马数字,第一章开始为阿拉伯数字,可以按如下步骤: 1.各部分插入分页符,这与插入两种页码无关,不过是为 ...
- Oracle 11g安装与使用
作为一个新手,学习Oracle,就连安装oracle都感觉到吃力! 经过不间断的搜罗.学习.尝试,找到一些比较有用的“指导”,罗列如下: 1. http://www.2cto.com/database ...
- GS玩家登录
玩家上线 这个过程看了很多很多次了,这里在看下 客户端打开,服务器收到libevent事件,然后new Channel这个过程都付给他各种指针,然后放到channel容器中 .客户端发送c2s_log ...
- Linux 的多线程编程的高效开发经验
http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...
- ASP.NET状态管理详解,让你明明白白
开发WinFrom的程序员可能不会在意维护应用程序的状态,因为WinFrom本身就在客户端运行,可以直接在内存中维护其应用程序状态.但ASP.NET应用程序在服务器端运行,客户端使用无状态的http协 ...