的確,這是一個很好的入口,更好的入口是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
|
|