论坛首页 Java企业应用论坛

用细粒度的Action做为你的系统权限

浏览 42114 次
该帖已经被评为精华帖
作者 正文
   发表时间: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里面判断权限?

偶真的想不明白了,是我什么地方没理解对吗?
0 请登录后投票
   发表时间: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等信息也难于获取.
0 请登录后投票
   发表时间: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,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.
0 请登录后投票
   发表时间:2005-01-23  
ruby 写道
如果这样来写ACTION,那Action也太不"纯粹"了,包含了太多和当前action无关的逻辑,既然是要进行界面元素的显示控制,就在界面上控制好了,比如用taglib,至于权限列表,保存在session,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.


确实不纯粹.但是,对于实例级别的权限控制,似乎没有更好的办法.

首先,明确一下.这里的需求是:实例级的权限控制(就是控制到谁对什么资源[的哪一个实例]具有什么操作).而不是功能级的权限控制(就是控制到谁对什么资源[不管哪一个实例都]具有什么操作).
实例级的权限控制,比如,A用户可以删除A帖子,但不能删除B帖子.它与具体资源的实例相关.
功能级的权限控制,比如,A用户可以删除帖子(A用户具有删除帖子的权限,不管什么帖子).它与具体资源的实例无关.
功能级的权限控制,与用户和资源类型相关,对于特定的用户来说,枚举资源类型得到的列表是确定的,确实可以用Session保存列表,在显示逻辑中处理.但是,实例级的权限控制,与具体的实例相关,对特定的用户,不可能枚举所有资源的实例.

这种情况下,只有Action的处理过程本身能够确定对于特定实例(ArticleId=xxx)做出权限判断.

从另一个角度来看,这里的Action实际上是一个"交互层",即,它服务于显示逻辑,显示逻辑需要一个"是否可以删除"的属性,那么它就应该提供,不管是从Session来取.还是从权限引擎来运算,这是另外一个问题.

这个做法应该说是合理的,但是,否有更好的方法,有待探讨.
0 请登录后投票
   发表时间:2005-01-23  
在action中的拦截只能拦截功能型的权限
而把实例型的的权限校验写在action里不是很好,action应该只是转发

觉得应该在action的下一层来实现这个校验,这样权限校验的耦合度还能第点,权限校验也方便重用。

比方说你要显示删除的时候要进行权限校验,真正删除的时候也要进行同样的校验,这样就应改把全校校验分离出来,我也不懂,瞎想的。
0 请登录后投票
   发表时间: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,显示界面元素时时取出对比一下,有此权限就显示此界面元素,没有就不显示.


在页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么?
0 请登录后投票
   发表时间:2005-01-23  
引用
页面控制很危险的,可能你的页面上控制不让他显示了,但是用户能手动输出地址呀,这不还是要转到内部去校验么?

这儿的"控制",控制的是页面元素的显示与否,而不是进行权限的控制,具体一点讲,我们除了在action(iterceptor)或者更低一层(service)里面进行权限控制以外,还要在页面上管理相关页面元素的显示与否,目的不是为了控制,而是为了页面的"干净",比如,一个不具备"删除帖子"这个权限子的用户登录了以后,最好是不要把帖子的删除功能的"链接"显示出来,这样页面不就更人性一点了?(和我无关都不要给我显示,显示出来的都是我能操作的),如果他知道这个删除功能的link,直接在浏览器里面手写提交,那么在服务器端自然还有进一步的验证,比如在Action里面,比如在Service里面,然后会再导航到相关信息提示或者出错页面.至少前面提到的实例一级的权限控制和功能一级的权限控制,我一般不会用到料度太细的实例一级,(比如对AA,BB用户提交的帖子有删除权限,而对CC这个领导提交的帖子却是只读的)...倒是很想听听这方面的管理,实例一级的控制,那权限的粒度这么小,管理不是非常麻烦?不过可能在电子政务和政府相关项目产品中会用得比较多一点吧
0 请登录后投票
   发表时间: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);;
  }
}


注意,以上代码,仅表概念,并未精心设计.

供探讨.
0 请登录后投票
   发表时间:2005-01-24  
如acegi:权限控制可以分前后两部分来做.前的可以基于url来做.后的基于方法拦截来做.前后的结合通过runAsManager来做到.例子就是里面的contact.后台的可以定义粗粒度的控制资源,前台再细化.并且分开开发,保证前后台的开发无关.
0 请登录后投票
   发表时间: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 的实现方式尚未了解(有时间了要去学习学习),如有理解失当之处,还望海涵.
0 请登录后投票
论坛首页 Java企业应用版

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