小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

AOP下的權(quán)限控制實(shí)現(xiàn)

 鳳舞天煌 2007-07-24

AOP下的權(quán)限控制實(shí)現(xiàn)

2006-07-10 05:00 作者: 陳景燕 陽國貴 出處: 計(jì)算機(jī)與信息技術(shù) 責(zé)任編輯:方舟
 
  摘要 面向方面的編程(AOP)是一種新的編程技術(shù),它彌補(bǔ)了面向?qū)ο蟮木幊?OOP)在跨越模塊行為上的不足。AOP引進(jìn)了Aspect,它將影響多個(gè)類的行為封裝到一個(gè)可重用模塊中,它允許程序員對(duì)橫切關(guān)注點(diǎn)進(jìn)行模塊化,從而消除了OOP引起的代碼混亂和分散問題,增強(qiáng)了系統(tǒng)的可維護(hù)性和代碼的重用性。本文分析傳統(tǒng)權(quán)限控制的實(shí)現(xiàn)方法,并研究了在AOP下權(quán)限控制的實(shí)現(xiàn)方法。

  關(guān)鍵詞 AOP;橫切關(guān)注點(diǎn); 設(shè)計(jì)模式; 權(quán)限控制

  OOP應(yīng)用開發(fā)面臨的問題

  面向?qū)ο蠹夹g(shù)很好地解決了軟件系統(tǒng)中角色劃分的問題。借助于面向?qū)ο蟮姆治觥⒃O(shè)計(jì)和實(shí)現(xiàn)技術(shù),開發(fā)者可以將問題領(lǐng)域的“名詞”轉(zhuǎn)換成軟件系統(tǒng)中的對(duì)象,從而很自然地完成從問題到軟件的轉(zhuǎn)換。

  但是,問題領(lǐng)域的某些需求卻偏偏不是用這樣的“名詞”來描述的。比如遇到這樣的問題:需要對(duì)系統(tǒng)中的某些方法進(jìn)行權(quán)限檢驗(yàn),這種需要權(quán)限檢驗(yàn)的方法散布在40多個(gè)類中。面對(duì)這種需求,應(yīng)該怎么辦呢?最直接的辦法就是:創(chuàng)建一個(gè)起類(或接口),將權(quán)限檢驗(yàn)的功能放在其中,并讓所有需要權(quán)限檢驗(yàn)的類繼承這個(gè)起類(或接口).如果這個(gè)需求是后期提出的.需要修改的地方就會(huì)分散在40多個(gè)文件中。這樣大的修改量,無疑會(huì)增加出錯(cuò)的幾率,并且加大系統(tǒng)維護(hù)的難度。

  人們認(rèn)識(shí)到,傳統(tǒng)的程序經(jīng)常表現(xiàn)出一些不能自然地適合單個(gè)程序模塊或者幾個(gè)緊密相關(guān)的程序模塊的行為例如權(quán)限檢驗(yàn)、日志記錄、對(duì)上下文敏感的錯(cuò)誤處理、性能優(yōu)化以及設(shè)計(jì)模式等等、我們將這種行為稱為“橫切關(guān)注點(diǎn)(crosscuttingconcern)”,因?yàn)樗缭搅私o定編程模型中的典型職責(zé)界限。如果使用過用于橫切關(guān)注點(diǎn)的代碼,您就會(huì)知道缺乏模塊性所帶來的問題。因?yàn)闄M切行為的實(shí)現(xiàn)是分散的,開發(fā)人員發(fā)現(xiàn)這種行為難以作邏輯思維、實(shí)現(xiàn)和更改。

  AOP的基本思想

  AOP是Aspect Oriented Programming的縮寫,意思是面向方面編程,一種新興的編程技術(shù)。AOP實(shí)際是GoF設(shè)計(jì)模式的延續(xù),設(shè)計(jì)模式孜孜不倦追求的是調(diào)用者和被調(diào)用者之間的解耦,AOP可以說也是這種目標(biāo)的一種實(shí)現(xiàn)。它可以解決OOP和過程化方法不能夠很好解決的橫切(crosscut)問題,如:事務(wù)、安全、日志等橫切關(guān)注。當(dāng)未來系統(tǒng)變得越來越復(fù)雜,橫切關(guān)注點(diǎn)就成為一個(gè)大問題的時(shí)候,AOP就可以很輕松的解決橫切關(guān)注點(diǎn)這個(gè)問題。


圖 1 把模塊作為一批關(guān)注點(diǎn)來實(shí)現(xiàn)

  通常,為滿足整個(gè)企業(yè)應(yīng)用某方面得需求,開發(fā)者(架構(gòu)師)需要整理出系統(tǒng)得關(guān)注點(diǎn)。圖 1形象地描述了關(guān)注點(diǎn),它能夠從AOP Aspect角度看待系統(tǒng)。比如,持久化、日志、應(yīng)用的業(yè)務(wù)邏輯通常被認(rèn)為是應(yīng)用需要解決的問題。因此,他們通常作為關(guān)注點(diǎn)看待。從整個(gè)系統(tǒng)角度考慮,它往往是由大量的關(guān)注點(diǎn)構(gòu)成的。

  我們把AOP看作是OOP的延續(xù),而不是競(jìng)爭(zhēng)對(duì)手。OOP在通常的場(chǎng)合下工作得很好,但在特定的領(lǐng)域里卻有所欠缺:舉例來說,如果我們必須為多個(gè)對(duì)象和方法應(yīng)用相同的事務(wù)行為,我們需要將同樣的代碼剪切/粘貼到每一個(gè)方法里。AOP讓我們可以把這類問題封裝到方面(aspect)中,從而更好地實(shí)現(xiàn)模塊化。AOP定義了“切入點(diǎn)”(pointcut)的概念,讓開發(fā)者可以從另一個(gè)角度來思考程序的結(jié)構(gòu),從而彌補(bǔ)了OOP的某些缺陷:如果需要對(duì)一組方法施加橫切的行為,就應(yīng)該攔截這些方法。

  在J2EE應(yīng)用開發(fā)中,我們主要用到AOP的攔截(interception)能力,它為我們提供了“在任何對(duì)象的方法調(diào)用前/后加入自定義行為”的能力,這使得我們可以處理企業(yè)應(yīng)用中的橫切(crosscutting)關(guān)注點(diǎn)(即:同時(shí)作用于多個(gè)對(duì)象的關(guān)注點(diǎn)),并且仍然保持強(qiáng)類型(不需要改變方法簽名)。

  權(quán)限控制的應(yīng)用程序?qū)崿F(xiàn)

  對(duì)于權(quán)限管理的做法,在WEB實(shí)現(xiàn)上,有以下幾種:

  ⑴ 利用Filter,對(duì)所有進(jìn)入的URI進(jìn)行解析,并取得當(dāng)時(shí)Session中的User信息,然后通過RBAC的機(jī)制,將此鏈接需要的權(quán)限與用戶擁有的權(quán)限進(jìn)行比較,然后進(jìn)行相應(yīng)的處理。這種做法有很多好處:簡(jiǎn)單,容易實(shí)現(xiàn),并且對(duì)系統(tǒng)侵入性也不強(qiáng)。這里URL就是RBAC中的資源了。這樣做的缺點(diǎn)是所有對(duì)數(shù)據(jù)的操作必須通過URL來體現(xiàn),這一點(diǎn)在現(xiàn)代的程序中不太好實(shí)現(xiàn)。如果采用Struts, XWork或者Tapestry,采用同一個(gè)URL(瀏覽器看來)進(jìn)行處理多項(xiàng)任務(wù)已不是什么稀奇的事。

 ?、?利用一個(gè)BaseServlet(Servlet+Jsp經(jīng)典模式)或者BaseAction(Struts模式)或者BasePage(Tapestry模式)或者BaseController(SpringMVC模式),對(duì)所有的請(qǐng)求先進(jìn)行過濾進(jìn)行權(quán)限操作,然后再處理。稍微看一下就知道這種模式跟Filter并無本質(zhì)不同。優(yōu)缺點(diǎn)同上。

  那么,如果要實(shí)現(xiàn)更為細(xì)致的權(quán)限操作,精確到某個(gè)方法的權(quán)限,典型的做法如下:

public someFunciton() {
 //權(quán)限判斷
 User user = context.getUser();
 if (user.canExecuteThisFunction()) {
  // do the business method
  // ...
 } else {
  throw new PermissionDeniedException();
 }
}

  這種做法能夠?qū)?quán)限的粒度控制到具體的業(yè)務(wù)方法,因此它的控制能力應(yīng)該是強(qiáng)大的??梢钥吹?,權(quán)限判斷部分對(duì)于每個(gè)方法幾乎是獨(dú)立的。

  這種在具體功能前加入權(quán)限操作檢驗(yàn)的實(shí)現(xiàn)方式有很多缺點(diǎn):

 ?、?每個(gè)功能類都需要相應(yīng)的權(quán)限檢驗(yàn)代碼,將程序功能和權(quán)限檢驗(yàn)混淆在一起,存在緊密的耦合性,擴(kuò)展修改難度大。

 ?、?以代理模式為每個(gè)功能類實(shí)現(xiàn)一個(gè)相應(yīng)的代理類,雖然解耦了程序功能和權(quán)限檢驗(yàn),但是,從某個(gè)角色的權(quán)限檢驗(yàn)這個(gè)切面考慮,涉及具體Proxy類太多,擴(kuò)展修改難度大。

  權(quán)限控制的J2EE容器實(shí)現(xiàn)

  在AOP概念沒有誕生前,J2EE規(guī)范已經(jīng)提供了關(guān)于權(quán)限控制的容器實(shí)現(xiàn)標(biāo)準(zhǔn),這種變遷結(jié)果如下圖所示:


圖2 權(quán)限控制的J2EE容器實(shí)現(xiàn)

  原來需要每個(gè)應(yīng)用程序?qū)崿F(xiàn)的權(quán)限Proxy轉(zhuǎn)為整個(gè)容器的Proxy實(shí)現(xiàn),其中JDK1.3以后的動(dòng)態(tài)代理API為這種轉(zhuǎn)換實(shí)現(xiàn)提供了技術(shù)保證。

  非常明顯,通過容器實(shí)現(xiàn)權(quán)限控制驗(yàn)證可以大大簡(jiǎn)化應(yīng)用程序的設(shè)計(jì),分離了應(yīng)用系統(tǒng)的權(quán)限關(guān)注,將權(quán)限控制變成了對(duì)J2EE容器服務(wù)器的配置工作。

  其實(shí),容器的權(quán)限實(shí)現(xiàn)也是一種從一個(gè)側(cè)面來解決問題方式,AOP概念誕生后,權(quán)限控制實(shí)現(xiàn)由此也帶來了兩個(gè)方向的變化:

  ⑴ J2EE容器級(jí)別的權(quán)限實(shí)現(xiàn),也就是容器自身的權(quán)限實(shí)現(xiàn)。

 ?、啤2EE應(yīng)用程序級(jí)別的權(quán)限實(shí)現(xiàn)。

  權(quán)限控制在容器級(jí)別實(shí)現(xiàn)似乎使得J2EE開發(fā)者感覺沒有靈活性和可擴(kuò)展性,其實(shí)象JBoss 4.0這樣的J2EE容器,由于引入了AOP概念,使得J2EE開發(fā)者在自己的應(yīng)用系統(tǒng)中能夠直接操縱容器的一些行為。容器和應(yīng)用系統(tǒng)由于AOP引入的Aspect切面,變得可以成為一體了。

  對(duì)于J2EE應(yīng)用系統(tǒng)開發(fā)者,能夠做到上述境界,必須的條件是對(duì)JBoss之類J2EE容器必須有足夠的了解,因?yàn)檫@些方式并不是J2EE標(biāo)準(zhǔn),有可能在移植到新的J2EE容器,這些知識(shí)和投入變得無用(也有可能將來J2EE擴(kuò)展其標(biāo)準(zhǔn))。

  很顯然,使用AOP實(shí)現(xiàn)J2EE應(yīng)用系統(tǒng)級(jí)別的權(quán)限控制,是解決上述移植風(fēng)險(xiǎn)的一個(gè)主要方法,但是帶來的缺點(diǎn)是必須親自從零開始做起,耗費(fèi)時(shí)間不會(huì)很短。

  AOP下的權(quán)限控制實(shí)現(xiàn)

  有了AOP,新的業(yè)務(wù)方法可以這樣寫:

public someFunciton() {
 // do the business method
 // ...
}

  沒有了額外的權(quán)限操作,這個(gè)業(yè)務(wù)方法看起來那么清晰自然。

  將對(duì)權(quán)限的操作作為一個(gè)Advice,并將Advisor關(guān)注到所有的業(yè)務(wù)方法(可能有某一個(gè)特定package),然后,剩下的事情就由RBAC以及AOP來完成了。通過這樣的分離,縱向的一個(gè)業(yè)務(wù)方法被分割為一個(gè)更為自然的業(yè)務(wù)方法和一個(gè)關(guān)注點(diǎn)。這個(gè)關(guān)注點(diǎn)寫法可能如下:

public class PermissionCheckAdvice implements MethodBeforeAdvice {
 public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
  //權(quán)限判斷
  if (!this.getContext().getUser().canExcute(this, arg0)) {
   throws new PermissionDeniedException();
  }
 }
}

  可能有個(gè)問題:如何取得context或者當(dāng)時(shí)上下文環(huán)境的User呢?答案是使用IoC(或稱Dependency Injection),將上下文環(huán)境或者User作為參數(shù)反向傳入到邏輯方法中。當(dāng)然,在傳入之前,這些變量是需要初始化的。這個(gè)初始化工作可以在SuperServlet中進(jìn)行,并且以Session單例的形式保存在應(yīng)用程序中。下面是Spring配置文件的例子:

<beans>
<!-- Bean configuration -->
<bean id="businesslogicbean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>IBusinessLogic</value>
</property>
<property name="target">
<ref local="beanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>thePermissionCheckBeforeAdvisor</value>
</list>
</property>
</bean>
<!-- Bean Classes -->
<bean id="beanTarget" class="BusinessLogic">
<property name="user"><<YOUR USER OBJECT>> </property>
</bean>
<!-- Advisor pointcut definition for before advice -->
<bean id="thePermissionCheckBeforeAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="thePermissionCheckBeforeAdvice"/>
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
<!-- Advice classes -->
<bean id="thePermissionCheckBeforeAdvice"
class="PermissionCheckBeforeAdvice"/>
</beans>

  結(jié)束語

  AOP引進(jìn)了Aspect,它將影響多個(gè)類的行為封裝到一個(gè)可重用模塊中,它允許程序員對(duì)橫切關(guān)注點(diǎn)進(jìn)行模塊化,從而消除了OOP引起的代碼混亂和分散問題,增強(qiáng)了系統(tǒng)的可維護(hù)性和代碼的重用性。利用AOP的攔截(interception)能力,它為我們提供了“在任何對(duì)象的方法調(diào)用前/后加入自定義行為”的能力,這使得我們可以處理企業(yè)應(yīng)用中的權(quán)限控制這一橫切關(guān)注點(diǎn),并且仍然保持強(qiáng)類型(不需要改變方法簽名),解耦了程序功能和權(quán)限檢驗(yàn)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多