锁定老帖子 主题:关于权限模块设计的一点思考
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (3)
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-30
权限控制分级,包括模块控制,URL控制,页面元素控制等等。
模块也页面元素都分配ID,然后写一个自定义标签来读取权限判断是否显示模块菜单或页面元素,比如按钮 URL控制可以所有的权限,包括控制模块,页面元素。 对已一个已经完成的系统 写一个权限的过滤器,在过滤器中对URL进行采集,存入数据库作为资源 然后给资源分配权限,再把权限绑定到角色,最后赋予用户角色。 关于采集的URL资源,不要采集数据参数,只采集视图参数,比如struts中有一个参数是指定由某个action中的那个方法执行的,具体的权限粒度可以控制到action中的方法。 对于特定的表,里面的记录不会发生变数,而且数据不多,URL的采集可以控制到具体数据库中的哪条记录。 |
|
返回顶楼 | |
发表时间:2008-10-30
pipilu 写道 页面上的每个按钮,对应的不也是url么
没错,按钮对应的也是一个url; 我的意思是说,对权限的完全控制的话,可以达到这样一个目的:比如一个delete按钮,项目经理登录,可以看到这个按钮,并且可以选中某些项,然后点击delete执行操作;而程序员登录,就不能看到这个delete按钮或者灰掉; 就是说怎么达到一个页面展现的权限控制问题; 当然,在页面展现根据不同权限展现不同功能按钮时,在真正执行到后台业务层也是需要权限验证的。 |
|
返回顶楼 | |
发表时间:2008-10-30
xiaoqulai 写道 权限控制分级,包括模块控制,URL控制,页面元素控制等等。
模块也页面元素都分配ID,然后写一个自定义标签来读取权限判断是否显示模块菜单或页面元素,比如按钮 URL控制可以所有的权限,包括控制模块,页面元素。 对已一个已经完成的系统 写一个权限的过滤器,在过滤器中对URL进行采集,存入数据库作为资源 然后给资源分配权限,再把权限绑定到角色,最后赋予用户角色。 xiaoqulai 写道 关于采集的URL资源,不要采集数据参数,只采集视图参数,比如struts中有一个参数是指定由某个action中的那个方法执行的,具体的权限粒度可以控制到action中的方法。
这个参数不采集,我想你的意思应该是RBAC模型中的URL资源,具体参数method是操作,不采集的话怎么控制具体权限呢? 你所说“具体的权限粒度可以控制到action中的方法”,没有明白你是怎么控制实现这个权限粒度的; xiaoqulai 写道 对于特定的表,里面的记录不会发生变数,而且数据不多,URL的采集可以控制到具体数据库中的哪条记录。
不明白你所谓“特定的表”; 又如何实现“URL的采集可以控制到具体数据库中的哪条记录”呢? |
|
返回顶楼 | |
发表时间:2008-10-30
andy54321 写道 pipilu 写道 页面上的每个按钮,对应的不也是url么
没错,按钮对应的也是一个url; 我的意思是说,对权限的完全控制的话,可以达到这样一个目的:比如一个delete按钮,项目经理登录,可以看到这个按钮,并且可以选中某些项,然后点击delete执行操作;而程序员登录,就不能看到这个delete按钮或者灰掉; 就是说怎么达到一个页面展现的权限控制问题; 当然,在页面展现根据不同权限展现不同功能按钮时,在真正执行到后台业务层也是需要权限验证的。 对不起,我回答的有些草率。 你说的这种需求我恰好也实现过。但并没有总结过。我就介绍一下我当时是怎么做的吧。 当时使用的是WebWork,页面端用的是FreeMarker。 我的做法是:做了两个拦截器,一个是AuthorizeInterceptor 一个是PermissionInterceptor。从名字可以看,前一个拦截器是验证用户是否登录,第二个验证用户访问的URL是否在他的权限范围内。 在AuthorizeInterceptor中如果用户确实登录了,就读取出他的权限列表(我采用的是字符串表示这个用户的权限信息的,用逗号分隔,如:action1,action2,action5 表示用户可以访问action1 action2 action5这三个action。(之所以在拦截器中取得权限列表,这样是为在修改用户权限后用户不必重新登录才能得到新的权限) 在PermissionInterceptor中,在拦截器中获取action的名字 String actionName = actionInvocation.getInvocationContext().getName(); 然后判断action名字是否在用户的权限列表中,如果不在,则返回到登录页面: if (permission.indexOf(actionName) == -1) { return Action.LOGIN; } 至于页面上控制按钮或超链接的显示,我用的是FreeMarker的表达示,意思跟上面的PermissionInterceptor中的一样: <#if permission?index_of("action2") != -1> <button>.... </#if> 我这样做的时候,有一个约束,那就是各action的名字不能有包含关系(即action名可以是bookView和bookEdit,不能是book和bookEdit,这样判断book是否在用户权限中时,有可能会因为bookEdit的存在而判断错误)。但我认为这个约束问题不大,因为action名字是设计人员自己定的,不需要它有多灵活,也不需要用户来自定义。 我感觉我对权限研究的没你多,现在正在研究spring的权限框架。上面的做法可能很粗糙,而且不好移植,我自己没有针对这个问题总结过,希望看到大家的意见。 |
|
返回顶楼 | |
发表时间:2008-10-30
tedeyang 写道 andy54321 写道 jander 写道 看看spring security, 它都给你解决了。
虽然有点繁琐。 不是有点繁琐,是非常繁琐,感觉太庞大了; 其实在解决方法上,我在进行spring security / jsecurity 之间的抉择, 前者过于庞大繁琐,后者刚刚加入apache,好多东西都没完善呢,当前文档、demo相当缺乏; 如果说Acegi庞大繁琐那是实话,说Spring Security 2.0繁琐那我不能苟同. 以我的经验,Security 2.0已经非常简洁了.接口设计优雅,,默认值合理,用来开发其实非常快. 我们以前是用过滤器做的URL权限控制,最近我改成了Spring Security实现, 写了十几行配置,再实现一个接口,再看看它的几个jsptag,登录和权限就都集成了,也不需要修改原来数据库结构.即便以后把用户信息改成LDAP实现,或者增加方法级别的安全设置,看手册那也是很easy的. 推荐看<<Spring in action>>第二版,在网上有公开章节的,其中含有Spring Security的相关内容,可能是地球上写得最好的教材了.(我本来照着官方网页的step by step入手的,弄了一天也没明白,嘿嘿.) 从这本书着手看,半天就能看懂,一天就能架起来. 我写过的URL控制性质的权限系统和Spring Security 2的架构设计比起来就像玩具一样,太粗糙了.看了人家的设计和代码,很被折服了一把. 唉... 其实复杂程度还是一样的,只是spring security作了很多的简化配置的工作。刚从acegi转过来的时候,很不习惯,一行一行看他的Schema. 另外,说它复杂吧,其实原理很简单,只要看清楚框架的几个主要类,就清楚了。 |
|
返回顶楼 | |
发表时间:2008-10-30
andy54321 写道 pipilu 写道 页面上的每个按钮,对应的不也是url么
没错,按钮对应的也是一个url; 我的意思是说,对权限的完全控制的话,可以达到这样一个目的:比如一个delete按钮,项目经理登录,可以看到这个按钮,并且可以选中某些项,然后点击delete执行操作;而程序员登录,就不能看到这个delete按钮或者灰掉; 就是说怎么达到一个页面展现的权限控制问题; 当然,在页面展现根据不同权限展现不同功能按钮时,在真正执行到后台业务层也是需要权限验证的。 是所谓的业务规则吗? |
|
返回顶楼 | |
发表时间:2008-10-30
说一下第二个问题:
第二个问题,我们系统中是这样解决的: 操作是树形的,权限也是树形的。 举个例子,url1 是跳转到一个页面,url1可以分配权限。 这个url的页面中,其实也可以通过树形,配置功能点,这些功能点,也有url。 在页面中,写一个permision的tag,页面中的链接,写在这个tag中。这个tag就去功能树上判断当前用户有没有这个url的权限,如果有,这个链接就打出来,如果没有,这个链接就不大出来。 还有,我们系统中,还有对数据库中表和字段的权限设置。 我们需要维护一个数据字典,建表的时候,并不是直接在数据库中建表的,而是通过数据字典这个功能点建表的。 查询的时候,我们通过数据字典,封装了查询,这样在开发查询的时候,可以通过配置得到查询结果,而不用写sql了。比如首先选择查询的表,然后设置表之间的连接关系,然后可以在页面设置查询条件,分组,排序统计,最好向数据库存储一个查询。当调用查询的时候,就可以通过这个查询id 得到查询结果。 我们可以通过数据字典,为每个用户配置每个表和每个字段的权限,当通过查询id得到查询结果的时候,就可以通过权限,判断改用户有没有对这个表的查询权限,如果有,再判断该用户没有对配置的查询的字段的权限,这是,如果一个字段,这个用户没有权限,那么,查询结果中就不包括这个字段,这样就实现了对表、字段的权限。而且简化了开发。因为sql不用写了,在页面配置一个查询就可以了。 我跟根据这个查询,还写了很多标签,比如,通过查询id 就可以利用标签,打印出列表等。列表后面的操作,也是可以配置的。这些操作,当然也会收url权限的控制。 |
|
返回顶楼 | |
发表时间:2008-10-31
基本原则还是采用角色权限的方法:Function -- Role -- User;
可以将需要管理的页面和表单元素作为最基本的颗粒:Url-->Page-->Elements; |
|
返回顶楼 | |
发表时间:2008-10-31
Acegi已经有对方法验证的机智。
继承 MethodDefinitionMap 重写 public void setMappings(List mappings) { } 建议去看一下MethodDefinitionMap 这个类的方法。 |
|
返回顶楼 | |
发表时间:2008-10-31
有这么复杂吗?
简单的权限用RBAC解决。复杂的用ACL解决。 应该是现在的标准吧。 这两个决定了谁有权限,然后用filter(web),aop(Class method)两头一截。ok。 当然,有时候业务规则有可能来添乱。那就在截的时候加入业务规则好了。比如说,spring security ,你可以实现自己基于业务规则的provider。 |
|
返回顶楼 | |