WEB应用数据权限控制
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WEB应用
数据权限控制
轻量级解决方案
aliang
2012-3-2
目录
1前言 (3)
2方案目标 (4)
3设计思路 (4)
4逻辑流程图 (6)
5数据库表设计 (7)
6关键技术点 (7)
7方案应用 (8)
8总结 (9)
1前言
很早就想把自己关于WEB应用中数据权限控制的思考写出来同大家分享,一直没有抽出时间,今天总算把此码成文字,以便能给对此感兴趣的朋友提供一种思路。
在许多应用开发中我们都会涉及到权限管理,当然,权限管理主要分两部分,即功能权限和数据访问权限。针对功能权限的控制,想必很多朋友都有很成熟的方案,在此不再废话。本文档主要探讨在WEB应用开发中的数据权限控制。
现在,许多的软件公司开发WEB应用都是利用开源框架S(Struts)S(Spring)H(Hibernate)或S(Struts)S(Spring)I(ibatis)来进行WEB应用开发的。关于数据权限的控制一般都是在代码开发时对访问数据库数据的SQL语句添加涉及数据权限控制的WHERE条件来实现。这样做的弊端就是在开发时就要详细分析哪些数据需要加入权限控制,并且这些关于数据权限控制的代码散布到整个应用中。一旦需要调整时就要对许多的SQL语句扒拉一边进行修改,很是耗费精力。
在做项目时,我也同样经受过这样的痛苦,于是我就想,能否把WEB应用的数据权限控制独立出来,就象Spring和切面编程一样,做到代码侵入度最低,灵活方便的添加数据权限控制。于是就有了我下面的思考和验证。
许多成熟的开发平台都有自己的一套关于数据权限控制的方案,这些控制都是依托数据集来完成的,通过把数据访问的规则加到数据集上来实现对数据访问的控制。但在WEB应用开发中,这些开源框架中都没有数据集的概念或展现,准确的说是很难在开发或运行状态下获取到有哪些数据集及数据项。
其实数据集的本质就是SQL语句返回的结果集(从XML或表格文件等形成的数据集不在此讨论范围),对数据集加入数据访问控制就是对SQL语句加入数据过滤条件。既然开源框架中没有数据集可用,那我们是否可以把数据访问控制直接应用到数据库表或视图上来达到目的呢?经过思考和验证完全可以做到。
2方案目标
做到代码低侵入度,在开发时不需要太多关注数据权限控制,可以在应用开发完成后,通过对表和视图定义权限控制策略,然后绑定到登录用户或功能URI 上来进行数据权限控制。数据访问控制需要调整时,只需要修改定义的权限策略即可。
3设计思路
数据权限控制需要解决的主要问题就是谁能访问哪些数据。只要搞定谁正在访问哪些表或视图,即可在运行时根据定义的数据访问策略加入数据权限控制。
如何找到访问数据库表和视图的访问者是个问题。WEB应用开发中一般登录人员的信息都是保存在Session中,但Session中保存的信息只能Struts的Action 或Servlet能够访问,Server层和ORM层都是不能访问Session中存储的登录者信息的,而最终访问数据库的SQL语句也只有在Datasource层才是最完全的,登录者信息不能通过调用对象方法时以参数方式传递,否则代码的改动和侵入度就太高了。要找到一种方法和一个点,即能获取到访问者信息又能获取到执行的SQL语句即可完成数据权限控制。
1、对需要进行数据权限控制的表和视图定义访问策略。
定义数据访问策略实际上就是定义要添加到表的Where条件。但同一个数据访问策略条件,不同的登录者访问将具有不同的结果。这就要求添加到Where 条件中要含有访问者信息。比如登录者只能看到自己所属机构的数据,那定义的访问策略条件中就要含有登录者所属机构号。要做到这点就要事先定义系统参数项,例如定义@LOGIN_ORG_ID代表登录者所属机构,在运行时添加数据访问权限(定义的数据访问策略)时,把定义的的数据访问策略中的@LOGIN_ORG_ID 替换为登录者所属机构号即可实现目的。当然这些定义的访问策略是要保存到数据库内。表的设计也很简单,只需要两个字段,一个BOJECT_NAME字段(存储表名或者视图名),一个SQL WHERE字段(存储用户访问控制的WHERE条件语句)。而且要开发一个定义这些策略的WEB功能。
一般常用的系统参数项有:
//当前请求地址的系统参数ID:"@REQUEST_URI";
//当前登录用户的IP的系统参数ID:"@LOGIN_IP";
//当前登录用户的系统ID的系统参数ID:"@LOGIN_USER_ID";
//当前登录用户的姓名的系统参数ID:"@LOGIN_USER_NAME";
//用户口令:"@DLOGIN_PASSWORD";
//当前登录用户的登录时间点的系统参数ID:"@LOGIN_DATETIME";
//当前登录用户的登录帐号的系统参数ID:"@LOGIN_USER_LOGID";
//当前登录用户的所属机构ID的系统参数ID:"@LOGIN_ORG_ID";
//当前登录用户的所属机构名称的系统参数ID:"@LOGIN_ORG_NAME";
//当前登录用户的所属部门ID的系统参数ID:"@LOGIN_DEPT_ID";
//当前登录用户的所属部门名称的系统参数ID:"@LOGIN_DEPT_NAME";
//当前登录用户的所属岗位ID的系统参数ID: "@LOGIN_STATION_ID";
//当前登录用户的所属岗位名称的系统参数ID:"@LOGIN_STATION_NAME";
2、开发一个为用户或角色和URI分配数据访问策略的WEB功能页面。
定义的数据访问策略不仅可以绑定到用户或角色,而且可以绑定到请求URI 上。为每一个登录用户在内存中维护一套数据访问策略数据,确实会占用一些内存资源,大部分访问数据的URI对每一个登录用户使用相同的数据策略,针对不同登录用户只是策略语句中需要替换的参数值不同而已,这样倒可以把数据访问策略绑定到URI请求上,那么对于系统URI的策略只需要维护一份数据即可。所以两种绑定方法(绑定到用户或URI)应该结合使用。
3、在登录验证功能中,当登录验证通过时初始化好定义的系统参数项值,同时获取绑定到此用户的数据访问策略,一并保存到Session内。
对于系统定义的参数项值,每一个登录用户的值都是不一样的,这就要为每个登录用户维护一套系统参数项值,其实也就是登录用户的属性信息,可以添加到MAP中并保存到此登录用户的Session中,以MAP表的键值对(map的key 就是定义的参数项)形式存储的目的就是为了替换数据策略条件中的参数项时方便获取,直接调用map的get(key)即可获取键值对应的值。
4、添加一个filter,在每次提交页面请求时把登录用户的信息放到线程内。
每次页面的URI请求,从请求开始到处理到最后的Response返回就是一个线程。我们把登录用户的信息存贮到线程内(包括本次请求的URI),在datasoure 提交SQL语句前取出线程内的登录用户信息,并根据定义的数据权限策略改写SQL语句添加数据访问条件,然后再提交给数据库执行改写后的SQL语句即可。