的确,这是一个很好的入口,更好的入口是Service层. 对于权限,以我目前的理解,是要分成两个问题:权限引擎和权限引入. 引擎就是要能提供一个可以切入应用逻辑的运算模块,做到: 1.能将从业务逻辑中提取出权限逻辑. 2.能够根据权限逻辑,对于当前操作进行运算,得到权限判断结果. 引擎是个相对独立的部分. 引入就是要能做到尽量透明的在系统中插入权限控制,必须: 1.尽量对业务透明. 2.提供合适的控制粒度. 引入可以采用AOP的Interceptor,只要在合理的层次上插入,就可以完成权限控制了. 在Action层插入,是一个方式.但是,因为Action层次的信息仍然不够丰富.更好的方式是在Service层次插入(对DomainObject操作).
robbin 写道
早先我做过一个系统,就是采用在Service层实现权限控制,但是后来发现不如在Action层实现起来方便。一方面是因为B/S应用中,客户端的请求动作本来就是一个一个的HTTP GET/POST,要做到最准确的权限控制,则必须针对Action。另一方面来说,如果你在Service层做权限控制,意味着你在Action还要写权限判定代码,那么就显得非常烦琐了。
如果要精确控制,必须要在比 Action 更细的层次做.举例来说: 论坛的帖子显示界面,如果当前用户对当前帖子有删除权限,则显示删除链接.否则,就不显示. 当前的操作(Action)是显示帖子,但是显示链接的逻辑判断需要对另外一个功能(删除功能)进行判断.这个判断是业务的必须,没有办法省略.
代码
- public class ViewArticle implements Action {
- public String execute() {
- ....
- }
- public boolean isDeleteAble() {
- ....
- }
- public boolean isEditAble() {
- ....
- }
- }
<script type="text/javascript">render_code();</script> 如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取. |
jackyz 写道
robbin 写道
早先我做过一个系统,就是采用在Service层实现权限控制,但是后来发现不如在Action层实现起来方便。一方面是因为B/S应用中,客户端的请求动作本来就是一个一个的HTTP GET/POST,要做到最准确的权限控制,则必须针对Action。另一方面来说,如果你在Service层做权限控制,意味着你在Action还要写权限判定代码,那么就显得非常烦琐了。
如果要精确控制,必须要在比 Action 更细的层次做.举例来说:
论坛的帖子显示界面,如果当前用户对当前帖子有删除权限,则显示删除链接.否则,就不显示. 当前的操作(Action)是显示帖子,但是显示链接的逻辑判断需要对另外一个功能(删除功能)进行判断.这个判断是业务的必须,没有办法省略.
代码
- public class ViewArticle implements Action {
- public String execute() {
- ....
- }
- public boolean isDeleteAble() {
- ....
- }
- public boolean isEditAble() {
- ....
- }
- }
<script type="text/javascript">render_code();</script>
如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取.
如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示. |
ruby 写道
如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.
确实不纯粹.但是,对于实例级别的权限控制,似乎没有更好的办法. 首先,明确一下.这里的需求是:实例级的权限控制(就是控制到谁对什么资源[的哪一个实例]具有什么操作).而不是功能级的权限控制(就是控制到谁对什么资源[不管哪一个实例都]具有什么操作). 实例级的权限控制,比如,A用户可以删除A帖子,但不能删除B帖子.它与具体资源的实例相关. 功能级的权限控制,比如,A用户可以删除帖子(A用户具有删除帖子的权限,不管什么帖子).它与具体资源的实例无关. 功能级的权限控制,与用户和资源类型相关,对于特定的用户来说,枚举资源类型得到的列表是确定的,确实可以用Session保存列表,在显示逻辑中处理.但是,实例级的权限控制,与具体的实例相关,对特定的用户,不可能枚举所有资源的实例. 这种情况下,只有Action的处理过程本身能够确定对于特定实例(ArticleId=xxx)做出权限判断. 从另一个角度来看,这里的Action实际上是一个"交互层",即,它服务于显示逻辑,显示逻辑需要一个"是否可以删除"的属性,那么它就应该提供,不管是从Session来取.还是从权限引擎来运算,这是另外一个问题. 这个做法应该说是合理的,但是,否有更好的方法,有待探讨. |
在action中的拦截只能拦截功能型的权限 而把实例型的的权限校验写在action里不是很好,action应该只是转发 觉得应该在action的下一层来实现这个校验,这样权限校验的耦合度还能第点,权限校验也方便重用。 比方说你要显示删除的时候要进行权限校验,真正删除的时候也要进行同样的校验,这样就应改把全校校验分离出来,我也不懂,瞎想的。 |
ruby 写道
jackyz 写道
robbin 写道
早先我做过一个系统,就是采用在Service层实现权限控制,但是后来发现不如在Action层实现起来方便。一方面是因为B/S应用中,客户端的请求动作本来就是一个一个的HTTP GET/POST,要做到最准确的权限控制,则必须针对Action。另一方面来说,如果你在Service层做权限控制,意味着你在Action还要写权限判定代码,那么就显得非常烦琐了。
如果要精确控制,必须要在比 Action 更细的层次做.举例来说:
论坛的帖子显示界面,如果当前用户对当前帖子有删除权限,则显示删除链接.否则,就不显示. 当前的操作(Action)是显示帖子,但是显示链接的逻辑判断需要对另外一个功能(删除功能)进行判断.这个判断是业务的必须,没有办法省略.
代码
- public class ViewArticle implements Action {
- public String execute() {
- ....
- }
- public boolean isDeleteAble() {
- ....
- }
- public boolean isEditAble() {
- ....
- }
- }
<script type="text/javascript">render_code();</script>
如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取.
如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.
在页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么? |
引用
页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么?
这儿的"控制",控制的是页面元素的显示与否,而不是进行权限的控制,具体一点讲,我们除了在action(iterceptor)或者更低一层(service)里面进行权限控制以外,还要在页面上管理相关页面元素的显示与否,目的不是为了控制,而是为了页面的"干净",比如,一个不具备"删除帖子"这个权限子的用户登录了以后,最好是不要把帖子的删除功能的"链接"显示出来,这样页面不就更人性一点了?(和我无关都不要给我显示,显示出来的都是我能操作的),如果他知道这个删除功能的link,直接在浏览器里面手写提交,那么在服务器端自然还有进一步的验证,比如在Action里面,比如在Service里面,然后会再导航到相关信息提示或者出错页面.至少前面提到的实例一级的权限控制和功能一级的权限控制,我一般不会用到料度太细的实例一级,(比如对AA,BB用户提交的帖子有删除权限,而对CC这个领导提交的帖子却是只读的)...倒是很想听听这方面的管理,实例一级的控制,那权限的粒度这么小,管理不是非常麻烦?不过可能在电子政务和政府相关项目产品中会用得比较多一点吧 |
控制权限,不但在要页面上,程序内部也必须控制,否则是相当危险的. 一般我的做法是在页面上进行粗粒度的控制,在程序内容进行细粒度的控制. 根据权限控制显示和根据权限控制执行在业务中,肯定都是必须的.缺少显示控制则界面将不够人性化.缺少执行控制则权限形同虚设. 这里举显示的例子,是为了表明,在Action的这个层次,除了一对一的执行控制以外,还有一对多的显示控制.所以,在Action这个层次并不是进行权限对应的合理层次. 控制应该是基于Action之下的Service层次.比如: 如此的框架:
代码
- public Interface Action {
- public String execute() throws ActionException;
- }
- public Interface Service {
- public void rule() throws ServiceExcception;
- pulblic Object flow() throws ServiceException;
- }
- public Class ServicePerformer {
- public boolean check(Service service) {
- boolean result = false;
- try {
- service.rule();
- result = true;
- } catch (ServiceException e) {
- }
- return result;
- }
- public Object perform(Service service) throws ServiceException {
- Object result = null;
- service.rule();
- result = service.flow();
- return result;
- }
- }
<script type="text/javascript">render_code();</script> 那么,具体的一个实现可能类似:
代码
- public class ViewAction implements Action {
-
- private Service deletService;
- private Service detailService;
-
- private ServicePerformer servicePerformer;
-
- private ArticleDetail articleDetail;
- public String execute() throws ActionException {
- try {
- articleDetail = servicePerformer.perform(detailService);
- return SUCCESS;
- } catch (ServiceException e) {
- return ERROR;
- }
- }
-
- public ArticleDetail getArticleDetail() {
- return articleDetail;
- }
-
- public boolean isDeleteAble() {
- return servicePerformer.check(deleteService);
- }
- }
<script type="text/javascript">render_code();</script> 注意,以上代码,仅表概念,并未精心设计. 供探讨.
引用
在 url 中可以分辩 /deleteArticle.do 这个操作,但是并不能分辩当前用户是否就是 articleId=123 这个帖子的作者.也就是说,如果不切入 Article 的 DomainObject 从 Article 中取出它的作者和当前用户进行比对, 那么,权限的判断肯定是难于进行的.
那么在 acegi 的方案中,对于这样的需求是怎么处理的呢?
1.acegi提供了可配置的voter,一个验证请求交由多个voter进行处理,已经提供了roleVoter.可以加入自定义的voter来处理. 2.什么是嵌入权限? 3.我想假如后台需要为多个前台,或者是未来的前台服务的时候,也才有必要引入这种复杂性. 我也是看看,没应用过,有什么不对之处,还望海涵. |
不管在是在service还是action加权限验证,实际是RBAC模块是可以分离的,我在去年的时候完成了这个模块,然后项目的时候只要把这个模块加进去就可以了。如果实际项目是可以通过url来控制权限的,那么就可以不用写一行代码。 在RBAC模块里完全可以做到很细的控制。 资源概念(可以是url,还有刚才看到有人说.do后面的参数那不到,参数当然可以拿的的,只不过url被切分成两部分而已,一部分就是参数.可以通过getQueryString得到) 资源就是想要的到的最终物质,我们可以给每一个资源定义一个权限,也可以给某一类资源定义一个权限,而web项目 url的tree特别容易用来管理资源。资源是一棵树,如果你有管理树根的权限那么就有了这颗树的所有权限。 权限概念 权限是对资源的一种保护访问.用户要访问A资源前提是用户必须有A资源的访问权限. 角色概念 实事上我们不会直接把权限赋予给用户,而是通过角色来赋予给用户,因为用户拥有某一种权限是因为用户扮演着某一种角色。 A是个经理,他管理着B公司,他拥有b,c,d的权限。实际是不是A有这个权限,而是因为Abo是经理。因为经理拥有b,c,d权限 所以很显然在权限划分上,我们会把权限赋予给某一个角色,而不是赋予给个人。这样带来的好处是 如果公司换了经理,那么只要再聘用一个人来做经理就可以了,而不会出现因为权限在个人手里导致权限被带走的情况 分组概念(分组也是一棵树,用户就是这里的叶子) 只有角色是不够的,B公司发现A有财务问题成立了一个财务调查小组,然后我们赋予了这个小组财务调查员的角色(注意是赋予小组这个角色).这样这个小组的所有人员 都有财务调查的资格。而不需要给小组的每个人都赋予这个角色(实际上已经拥有了),分组概念也适合部门,因为任何一个部门在公司里或者社会上都在扮演着一个泛的角色。 用户 用户一定是属于某一个分组的,不存在不属于分组的用户.不过用户可以直接扮演(获得)角色,或者通过属于的分组来得到角色 最后一个概念 判断用户有没有访问资源的权限就看这个用户有没有访问这个资源的权限,也就是说分组,分部门,分角色最终是以权限来实现对资源的访问控制 |
nihongye 写道
1.acegi提供了可配置的voter,一个验证请求交由多个voter进行处理,已经提供了roleVoter.可以加入自定义的voter来处理.
2.什么是嵌入权限?
3.我想假如后台需要为多个前台,或者是未来的前台服务的时候,也才有必要引入这种复杂性.
1.voter?在上述应用中,是否可以设想有一个voter,它所做的事情是否就是根据articleId从数据库取出article.author,与当前用户进行比对,如果相符就vote同意? 2.嵌入权限的意思就是,在系统设计之初不对权限做太多的设计,在系统的外部通过可配置的权限模块来给系统引入权限逻辑. 3.这个前台后台没有听太懂. 象上述作例子论坛这样的系统,没有特定的后台管理界面.版主,普通浏览者,匿名用户等等,所有用户都使用相同的界面.只是界面上显示的内容不同.比如,在一个看帖界面中,版主能看到删除链接,点击该链接能执行删除当前帖子的操作.但,匿名用户看不见删除链接,即使用户自己拼出删除链接,也不能执行删除操作. 继续探讨. |
1.是 2.同意. 3.后台和前台不是你说的意思.是指如: ServiceBeanA代表后台(相对稳定的一层). ActionC,ActionD,ActionE代表前台,或者URLC,URLD,URLE |
|