论坛首页 Java企业应用论坛

大家的权限都是怎么实现的,有什么好的方案没有? 欢迎交流

浏览 49308 次
该帖已经被评为精华帖
作者 正文
   发表时间:2011-08-03   最后修改:2011-08-03
sdnasky 写道
george_space 写道
oolala 写道
sdnasky 写道
数据模型不是关键,只要保存用户-权限关系就行了
设计上的关键是找到权限控制点
界面级:自定义标签可以实现
URL级:Filter可以实现
后台方法级:AOP可以实现
数据级:良好设计+AOP可以实现

即使没有良好的设计,针对不同需求,在控制点写拦截处理类就行了,只是重复代码的问题

权限的关键是:找到控制点,拦截,然后做你想做的事情


分析得不错


  • sdnasky写到:
  • 界面级:自定义标签可以实现

我现在也是使用自定义标签来实现的界面元素控制:
<eagle:hasPermission name="saveOrder"> 
    <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存订单" />
</eagle:hasPermission>

问题:现在标签中定义拥有“saveOrder”权限的人,可以看见保存订单的按钮,但是项目交给客户以后,客户想让拥有“kissGirl”权限的人,也能看见保存订单按钮,那么你是不是要去修改页面?

这样每次权限定义发生变动,都要去修改页面自定义标签,跟硬编码写死权限判断有什么分别?

  • sdnasky写到:
  • 数据级:良好设计+AOP可以实现

问题:怎么实现?这个是关键!
举个简单的例子:
一个列表页,要求:普通员工看见自己发表的信息(标题、发布时间);
部门经理看见本部门的信息(标题、发布时间 + 发布人积分);
管理员看见所有的信息(标题、发布时间、发布人积分 + 删除/修改)按钮。

这个列表页是使用web service从美国加利福尼亚州总部读取的,问,如何实现数据权限控制?

这样的需求,不是一个小小的AOP拦截就能够搞定的,即使能搞定,其复杂度也是超乎想象的。

有一个比较笨的方法,就是在服务端做权限逻辑判断,组装出当前权限应该看到的数据量和数据列,然后使用json
格式传递到视图层进行渲染,这样就相当于把视图端自定义标签所做的判断,移动到了服务端。
服务端使用策略模式,针对不同的权限,执行不同的查询逻辑;
如果有新的查询逻辑出来,就更麻烦了,理论上可以使用“页面上可视化配置 = > 动态生成java类 => 动态加载新的查询逻辑类 => 动态执行新的查询逻辑类”这样的方式来把新逻辑插入当前的判断中,但是这仅仅是理论上的设计,实际做起来,可不是上面这样三言两语能够“说”完的。

要做到数据权限的精确控制,除了和系统紧密耦合的做法和硬编码判断的做法,我还没有发现更好的实现,请楼下大牛们赶紧赐教。
----------------------------------------------------


1.标签使用错误,界面标签只是标识出该控制点的唯一标识,剩下的事情由标签处理函数去取出用户权限列表,并且判断用户是否含有该权限点的唯一标识

<eagle:hasPermission id="xxx.jsp.saveorder">
    <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存订单" />
</eagle:hasPermission>

权限标识可以使用命名规则,用来区分不同类型权限:菜单,界面控件,或其他的

2.取数据的方法如果设计合理,预留了可以方便添加数据过滤的接口,用AOP拦截方法调用,修改输入参数即可
即使设计不好,用AOP拦截方法调用(不调用现有方法),直接调用全新的含有数据过滤的取数据方法即可,无非是有重复代码而已



1、我的权限标签支持ant式过滤的,类似下面:

<eagle:hasPermission id="user.customer.*,user.manager.*"> 
    <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存订单" />
</eagle:hasPermission>

但是问题的关键是:如果现在客户要求“user.teamleader.*”也能保存订单,你是不是要把“user.teamleader.*”手动添加到权限标签里面去?是不是要改动视图层页面?是不是跟修改硬编码也简单不到哪里去?

2、AOP方式没有亲身实践过,不知道是否行得通,不做评论。

下面是我现在的初步设计,总体的意图是将查询逻辑留给软件部署者来在界面中配置:



执行阶段时序图:

  • 大小: 135.2 KB
  • 大小: 52.6 KB
0 请登录后投票
   发表时间:2011-08-03  
实际解决上述两个case
1. 页面标识出该页面保存按钮权限id为xxx.jsp.saveorder,谁拥有这个标识谁就能访问,“拥有“saveOrder”权限的人”和“拥有“kissGirl”权限的人”都是角色,都不是最细致的针对唯一权限标识点,不管你用什么数据模型,找到 用户-权限唯一标识 关系即可

2.如果美国总部“设计良好”提供了方便添加过滤条件的参数,AOP拦截调用修改传入参数即可,即使美国总部是猪,没关系,AOP获得返回结果,针对返回结果编写处理类,然后将处理之后的结果返回即可,至于界面上的“删除/修改 按钮”,留给界面级权限模块处理,同上甚至有跟多要求,针对每一条数据处理都不一样,比如张山可以“删除/修改 按钮”135条,李四可以“删除/修改 按钮”2468条,都没问题,权限标识
xxx.jsp.deleteupdate.1
xxx.jsp.deleteupdate.2
xxx.jsp.deleteupdate.3
xxx.jsp.deleteupdate.4
xxx.jsp.deleteupdate.5
...
标识后接上ID即可,至于处理标签如何处理,根据规则来就行了
0 请登录后投票
   发表时间:2011-08-03  
最后共享一个这边的权限设计
其他数据模型不看了

权限表含有3个字段
expression 可以为空,该权限控制点的处理表达式
script     可以为空,该权限控制点的处理表脚本
handle     可以为空,该权限控制点的处理表类

系统需要引入脚本引擎,我们这里用的是jbpm的脚本引擎,最后搞不定就只有反射处理类出马了,不要指望用户直接写脚本,用户最多自己写简单expression 什么 money>10000 , level=经理 啥的,如果用户有特殊需求,根据情况,我们写好script或者handle提供用户下拉选择,填写参数。
0 请登录后投票
   发表时间:2011-08-03   最后修改:2011-08-03
george_space, 关键是你们的权限标签保存的不是权限点,而是角色,因此没辙
权限标签就是标识出,这块范围的权限标识就可以了,权限点跟角色的关系交给数据库动态处理就行了
至于有无权限的判定处理,默认处理,表达式,脚本,处理类,各种工具提供选择
0 请登录后投票
   发表时间:2011-08-03   最后修改:2011-08-03
sdnasky 写道
george_space, 关键是你们的权限标签保存的不是权限点,而是角色,因此没辙
权限标签就是标识出,这块范围的权限标识就可以了,权限点跟角色的关系交给数据库动态处理就行了
至于有无权限的判定处理,默认处理,表达式,脚本,处理类,各种工具提供选择

我的权限标签,既可以制定一个或若干个权限,或者使用 user.*这样的ant通配符,
也可以制定一个或若干个角色,或者使用role.*这样的ant通配符,
我的权限系统是我自己设计的,因此不存在受制于人不便修改的问题。

如果有更好的实现方式,我很乐意及时来改进,关键是到现在为止,我还没发现比我的权限标签更通用,更智能的“新标签方式”

使用标签方式控制页面元素,本身就是一种硬编码的变通写法,如果再使用标签来控制列表页的列数量,那简直就是硬编码中的战斗硬,金刚石中的硬钻头,硬到无地自容了,没有任何通用性可言。

使用权限标签来定义页面元素的显示、隐藏,定义列表页的列数量,这样的做法只能适用于项目型软件,不适用或者说不能完全适用于产品型软件。
0 请登录后投票
   发表时间:2011-08-03  
sdnasky 写道
george_space, 关键是你们的权限标签保存的不是权限点,而是角色,因此没辙
权限标签就是标识出,这块范围的权限标识就可以了,权限点跟角色的关系交给数据库动态处理就行了
至于有无权限的判定处理,默认处理,表达式,脚本,处理类,各种工具提供选择

你说的标签方式我理解,就是:

标签定义一个ID="helloGirl"  => 标签实现类中判断当前登录者的权限列表,遍历权限所管辖的所有页面元素ID,看看是否包含本标签的ID:helloGirl => 如果包含,显示标签body,如果不包含,不显示标签body

是不是这个意思?
0 请登录后投票
   发表时间:2011-08-03  
george_space 写道

2、AOP方式没有亲身实践过,不知道是否行得通,不做评论。

下面是我现在的初步设计,总体的意图是将查询逻辑留给软件部署者来在界面中配置:



偶卖糕,这也太复杂了吧,用户都是猪,不懂编程,针对一个权限点的规则变更有这么频繁么?
动态编译类似于我们系统的表达式,脚本。
表达式可以给用户做做,脚本,处理类还是我们写好给用户填空好了,通盘考虑,为了这么点变更,引入的开发成本划算么?
类似的权限需求变更由
“管理员可以编辑删除” 改为 “A型管理员只能编辑删除奇数行” “B型管理员只能编辑删除偶数行”

我觉得没有必要让用户自己去配置,我们编写脚本存数据库就可以了
0 请登录后投票
   发表时间:2011-08-03  
george_space 写道
sdnasky 写道
george_space, 关键是你们的权限标签保存的不是权限点,而是角色,因此没辙
权限标签就是标识出,这块范围的权限标识就可以了,权限点跟角色的关系交给数据库动态处理就行了
至于有无权限的判定处理,默认处理,表达式,脚本,处理类,各种工具提供选择

你说的标签方式我理解,就是:

标签定义一个ID="helloGirl"  => 标签实现类中判断当前登录者的权限列表,遍历权限所管辖的所有页面元素ID,看看是否包含本标签的ID:helloGirl => 如果包含,显示标签body,如果不包含,不显示标签body

是不是这个意思?


是的,不过"helloGirl"容易引起歧义,我们的做法是命名规则 页面.模块.控件
如果权限id为 xxx.jsp.xx.btnSave,你看不就解决了你的问题了么

通配符应该作为角色-权限关系存于数据库,你们的问题就是由于通配符引起的,一个点就是一个点,要1对多就用数据库存关系
0 请登录后投票
   发表时间:2011-08-03  
为什么自定义权限标签无法控制列?当然可以啦
每个列一个权限标识,有标识,显示,没有标识忽略
权限标签加在populate单元格上
0 请登录后投票
   发表时间:2011-08-03  
留个爪。。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics