锁定老帖子 主题:用细粒度的Action做为你的系统权限
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-01-21
引用 本质上一个Action代表了一个请求的URL地址,而B/S项目本质上也就是只能根据URL来确定是否具备访问权限,从原理上来说,也是合适的。
前半句能理解,但是后面的偶的脑袋就开不了窍了。 为什么说只能根据URL来确定呢?况且光凭借一个URL够么?用户的角色之类的信息可没有放在URL里面啊。 引用 所以我觉得在Action上面再抽象出来一层Module,针对Module设置权限比较好。
这里的Module究竟是指什么呢?他和action和业务逻辑的关系是怎么样的?在我的脑子里找不到和这个概念对应的部分。 引用 一方面是因为B/S应用中,客户端的请求动作本来就是一个一个的HTTP GET/POST,要做到最准确的权限控制,则必须针对Action
这个和上面说的针对Module做权限是否有矛盾? 引用 另一方面来说,如果你在Service层做权限控制,意味着你在Action还要写权限判定代码,那么就显得非常烦琐了。
既然在service做权限控制,为什么又会在Action里面判断权限? 偶真的想不明白了,是我什么地方没理解对吗? |
|
返回顶楼 | |
发表时间:2005-01-21
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(); { .... } } 如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取. |
|
返回顶楼 | |
发表时间:2005-01-21
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(); { .... } } 如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取. 如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示. |
|
返回顶楼 | |
发表时间:2005-01-23
ruby 写道 如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.
确实不纯粹.但是,对于实例级别的权限控制,似乎没有更好的办法. 首先,明确一下.这里的需求是:实例级的权限控制(就是控制到谁对什么资源[的哪一个实例]具有什么操作).而不是功能级的权限控制(就是控制到谁对什么资源[不管哪一个实例都]具有什么操作). 实例级的权限控制,比如,A用户可以删除A帖子,但不能删除B帖子.它与具体资源的实例相关. 功能级的权限控制,比如,A用户可以删除帖子(A用户具有删除帖子的权限,不管什么帖子).它与具体资源的实例无关. 功能级的权限控制,与用户和资源类型相关,对于特定的用户来说,枚举资源类型得到的列表是确定的,确实可以用Session保存列表,在显示逻辑中处理.但是,实例级的权限控制,与具体的实例相关,对特定的用户,不可能枚举所有资源的实例. 这种情况下,只有Action的处理过程本身能够确定对于特定实例(ArticleId=xxx)做出权限判断. 从另一个角度来看,这里的Action实际上是一个"交互层",即,它服务于显示逻辑,显示逻辑需要一个"是否可以删除"的属性,那么它就应该提供,不管是从Session来取.还是从权限引擎来运算,这是另外一个问题. 这个做法应该说是合理的,但是,否有更好的方法,有待探讨. |
|
返回顶楼 | |
发表时间:2005-01-23
在action中的拦截只能拦截功能型的权限
而把实例型的的权限校验写在action里不是很好,action应该只是转发 觉得应该在action的下一层来实现这个校验,这样权限校验的耦合度还能第点,权限校验也方便重用。 比方说你要显示删除的时候要进行权限校验,真正删除的时候也要进行同样的校验,这样就应改把全校校验分离出来,我也不懂,瞎想的。 |
|
返回顶楼 | |
发表时间:2005-01-23
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(); { .... } } 如果是对 Action 进行控制的话,恐怕就需要构造一个 URL 再行判断了.此外,Role等信息也难于获取. 如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示. 在页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么? |
|
返回顶楼 | |
发表时间:2005-01-23
引用 页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么?
这儿的"控制",控制的是页面元素的显示与否,而不是进行权限的控制,具体一点讲,我们除了在action(iterceptor)或者更低一层(service)里面进行权限控制以外,还要在页面上管理相关页面元素的显示与否,目的不是为了控制,而是为了页面的"干净",比如,一个不具备"删除帖子"这个权限子的用户登录了以后,最好是不要把帖子的删除功能的"链接"显示出来,这样页面不就更人性一点了?(和我无关都不要给我显示,显示出来的都是我能操作的),如果他知道这个删除功能的link,直接在浏览器里面手写提交,那么在服务器端自然还有进一步的验证,比如在Action里面,比如在Service里面,然后会再导航到相关信息提示或者出错页面.至少前面提到的实例一级的权限控制和功能一级的权限控制,我一般不会用到料度太细的实例一级,(比如对AA,BB用户提交的帖子有删除权限,而对CC这个领导提交的帖子却是只读的)...倒是很想听听这方面的管理,实例一级的控制,那权限的粒度这么小,管理不是非常麻烦?不过可能在电子政务和政府相关项目产品中会用得比较多一点吧 |
|
返回顶楼 | |
发表时间:2005-01-24
ruby 写道 引用 页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么?
这儿的"控制",控制的是页面元素的显示与否,而不是进行权限的控制,具体一点讲,我们除了在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; } } 那么,具体的一个实现可能类似: public class ViewAction implements Action { // 一个Action引用了两个Service; 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; } } // 传递给显示逻辑用的DTO public ArticleDetail getArticleDetail(); { return articleDetail; } // 传递给显示逻辑用的显示控制用属性 public boolean isDeleteAble(); { return servicePerformer.check(deleteService);; } } 注意,以上代码,仅表概念,并未精心设计. 供探讨. |
|
返回顶楼 | |
发表时间:2005-01-24
如acegi:权限控制可以分前后两部分来做.前的可以基于url来做.后的基于方法拦截来做.前后的结合通过runAsManager来做到.例子就是里面的contact.后台的可以定义粗粒度的控制资源,前台再细化.并且分开开发,保证前后台的开发无关.
|
|
返回顶楼 | |
发表时间:2005-01-25
to:nihongye
对于 url 拦截型的方式,有问题想要请教一下. 通过 url 肯定是难于获取目标对象的完整信息的.比如,删除帖子的URL:http://www.yourbbs.com/deleteArticle.do?articleId=123 而帖子删除动作的权限规则是: 版主或者文章的作者可以删除文章. 在 url 中可以分辩 /deleteArticle.do 这个操作,但是并不能分辩当前用户是否就是 articleId=123 这个帖子的作者.也就是说,如果不切入 Article 的 DomainObject 从 Article 中取出它的作者和当前用户进行比对, 那么,权限的判断肯定是难于进行的. 那么在 acegi 的方案中,对于这样的需求是怎么处理的呢? 此外,对于嵌入权限,我觉得:如果能够不动现有系统,那就不要去动.如果必须要动现有系统,那就尽量少动. nihongye 写道 前面的要做URL拦截.后面的要做方法拦截.前后结合的要通过runAsManager来做到.
这,是否比较复杂了呢? 对于 acegi 的实现方式尚未了解(有时间了要去学习学习),如有理解失当之处,还望海涵. |
|
返回顶楼 | |