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的权限的配置和验证的更多相关文章

  1. 基于思科模拟器的AAA配置与验证

    拓扑图: 地址表如图所示 三个路由器之间采用ospf协议达到互通 先做ping通测试 由ApingB 由ApingC 配置AAA认证 在R1上 R1(config)#username shuaiqiy ...

  2. Forms身份验证和基于Role的权限验证

    Forms身份验证和基于Role的权限验证 从Membership到SimpleMembership再到ASP.NET Identity,ASP.NET每一次更换身份验证的组件,都让我更失望.Memb ...

  3. webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制

    webapi框架搭建系列博客 在上一篇的webapi框架搭建-安全机制(三)-简单的基于角色的权限控制,某个角色拥有哪些接口的权限是用硬编码的方式写在接口上的,如RBAuthorize(Roles = ...

  4. SVN版本库(访问权限)配置实例笔记

    http://blog.csdn.net/zjianbo/article/details/8578297 SVN版本库(访问权限)配置实例笔记 本系列文章由ex_net(张建波)编写,转载请注明出处. ...

  5. asp.net权限控制配置web.config

    项目下 有三个文件夹 A,B,C 验正方式是 Forms 验正 我要设置他们的访问权限为, A,匿名可访问 B,普通用户授权后才能访问 C,只允许管理员访问 <configuration> ...

  6. 【shiro】(5)---基于Shiro的权限管理

    基于Shiro的权限管理项目搭建 前面写了四篇有关权限的文章,算是这篇文章的铺垫了.这篇文章采用 开发环境           JDK1.8          Eclipse          Mav ...

  7. 【shiro】(2)---基于RUL的权限管理

    基于RUL的权限管理 我想在写shiro权限管理认证前,先来一个基于URL实现的权限管理控制. 一.基于URI的权限业务逻辑  实现思路:       将系统操作的每个url配置在权限表中,将权限对应 ...

  8. webapi框架搭建-安全机制(三)-简单的基于角色的权限控制

    webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...

  9. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

随机推荐

  1. windows下将多个文件里面的内容合并成一个一个文件

    如题:例如有多个章节的小说,现在要把他们合并成一个txt文件. 利用windows自带cmd工具: 一.拷贝合并1.将你的txt文档按照顺序分别命名为01.txt 02.txt 03.txt……2.将 ...

  2. Netsharp快速入门(之6) 基础档案(创建导航菜单)

    作者:秋时 杨昶   时间:2014-02-15  转载须说明出处 1.1     创建导航菜单 1.在Demo节点下,录入路径名称,并在下方录入两个导航页签名 2.建立分类,只要填路径名 3.双击基 ...

  3. HDU 5792 World is Exploding 树状数组+枚举

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Time Limit: 2000/1000 MS (Ja ...

  4. ubuntu10.04编译内核不显示grub菜单解决

    问题描述:        ubuntu10.04 内核版本2.6.32.28编译内核之后版本2.6.37.6,系统在编译完内核之后,不显示grub菜单 参考资料:            http:// ...

  5. [poj 1741]Tree 点分治

    题意 求树上距离不超过k的点对数,边权<=1000 题解     点分治.     点分治的思想就是取一个树的重心,这种路径只有两种情况,就是经过和不经过这个重心,如果不经过重心就把树剖开递归处 ...

  6. VSFTPD全攻略(/etc/vsftpd/vsftpd.conf文件详解)

    /etc/vsftpd/vsftpd.conf文件详解,分好类,方便大家查找与学习 #################匿名权限控制############### anonymous_enable=YE ...

  7. On Explainability of Deep Neural Networks

    On Explainability of Deep Neural Networks « Learning F# Functional Data Structures and Algorithms is ...

  8. HDU4784 Dinner Coming Soon(dp)

    当时区域赛的一道题.题意大概是这样的,有一个1~N的图,然后你要从1->N,其中每经过一条边需要消耗你的时间和金钱,每到一个地方可以选择什么都不做,或者买一包盐,卖一包盐,身上不能同时有超过B包 ...

  9. css display visibility

    当visibility被设置为"hidden"的时候,元素虽然被隐藏了,但它仍然占据它原来所在的位置.注意,当元素被隐藏之后,就不能再接收到其它事件了. display属性就有一点 ...

  10. 有趣 GIF 动图集 - 仿佛每张小动图都诉说了一个小笑话或者小故事

    点这里 来自法国南特(Nantes)的 Guillaume Kurkdjian 目前还是个学生.Kurkdjian 擅长创作一些平面动态图像,这些有趣的小动图仿佛每张都诉说了一个小笑话或者小故事,像个 ...