JAVA學(xué)習(xí)點點滴滴

          用開放的腦子去闖蕩;用開闊的視野去拼搏;用平和的身心去磨練;用美好的理想去追求!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            18 隨筆 :: 1 文章 :: 2 評論 :: 0 Trackbacks
          matrixeditor 發(fā)表于 2005-07-28 11:06:41
          作者:Matrixeditor???? 來源:BEA dev2dev
          評論數(shù):4 點擊數(shù):6,815???? 投票總得分:8 投票總?cè)舜?3
          關(guān)鍵字:

          摘要:

          Acegi安全系統(tǒng),是一個用于Spring Framework的安全框架,能夠和目前流行的Web容器無縫集成。它使用了Spring的方式提供了安全和認(rèn)證安全服務(wù),包括使用Bean Context,攔截器和面向接口的編程方式。因此,Acegi安全系統(tǒng)能夠輕松地適用于復(fù)雜的安全需求。
          ?????????? Acegi安全系統(tǒng),是一個用于Spring Framework的安全框架,能夠和目前流行的Web容器無縫集成。它使用了Spring的方式提供了安全和認(rèn)證安全服務(wù),包括使用Bean Context,攔截器和面向接口的編程方式。因此,Acegi安全系統(tǒng)能夠輕松地適用于復(fù)雜的安全需求。
          ?????? 安全涉及到兩個不同的概念,認(rèn)證和授權(quán)。前者是關(guān)于確認(rèn)用戶是否確實是他們所宣稱的身份。授權(quán)則是關(guān)于確認(rèn)用戶是否有允許執(zhí)行一個特定的操作。
          ?????? 在Acegi安全系統(tǒng)中,需要被認(rèn)證的用戶,系統(tǒng)或代理稱為"Principal"。Acegi安全系統(tǒng)和其他的安全系統(tǒng)不同,它并沒有角色和用戶組的概念。
          Acegi系統(tǒng)設(shè)計
          ??關(guān)鍵組件
          ??????Acegi安全系統(tǒng)包含以下七個關(guān)鍵的功能組件:
          ????????1 Authentication對象,包含了Principal,Credential和Principal的授權(quán)信息。同時還可以包含關(guān)于發(fā)起認(rèn)證請求的客戶的其他信息,如IP地址。
          ????????2 ContextHolder對象,使用ThreadLocal儲存Authentication對象的地方。
          ????????3 AuthenticationManager,用于認(rèn)證ContextHolder中的Authentication對象。
          ????????4 AccessDecissionManager,用于授權(quán)一個特定的操作。
          ????????5 RunAsManager,當(dāng)執(zhí)行特定的操作時,用于選擇性地替換Authentication對象。
          ????????6 Secure Object攔截器,用于協(xié)調(diào)AuthenticationManager,AccessDecissionManager,RunAsManager和特定操作的執(zhí)行。
          ????????7 ObjectDefinitionSource,包含了特定操作的授權(quán)定義。
          ??????這七個關(guān)鍵的功能組件的關(guān)系如下圖所示(圖中灰色部分是關(guān)鍵組件):


          安全管理對象
          ?????? Acegi安全系統(tǒng)目前支持兩類安全管理對象。
          ?????? 第一類的安全管理對象管理AOP Alliance的MethodInvocation,開發(fā)人員可以用它來保護Spring容器中的業(yè)務(wù)對象。為了使Spring管理的Bean可以作為MethodInvocation來使用,Bean可以通過ProxyFactoryBean和BeanNameAutoProxyCreator來管理,就像在Spring的事務(wù)管理一樣使用。
          ?????? 第二類是FilterInvocation。它用過濾器(Filter)來創(chuàng)建,并簡單地包裝了HTTP的ServletRequest,ServletResponse和FilterChain。FilterInvocation可以用來保護HTTP資源。通常,開發(fā)人員并不需要了解它的工作機制,因為他們只需要將Filter加入web.xml,Acegi安全系統(tǒng)就可以工作了。

          安全配置參數(shù)
          ?????? 每個安全管理對象都可以描述數(shù)量不限的各種安全認(rèn)證請求。例如,MethodInvocation對象可以描述帶有任意參數(shù)的任意方法的調(diào)用,而FilterInvocation可以描述任意的HTTP URL。
          ?????? Acegi安全系統(tǒng)需要記錄應(yīng)用于每個認(rèn)證請求的安全配置參數(shù)。例如,對于BankManager.getBalance(int accountNumber)方法和BankManager.approveLoan(int applicationNumber)方法,它們需要的認(rèn)證請求的安全配置很不相同。
          ?????? 為了保存不同的認(rèn)證請求的安全配置,需要使用配置參數(shù)。從實現(xiàn)的視角來看,配置參數(shù)使用ConfigAttribute接口來表示。Acegi安全系統(tǒng)提供了ConfigAttribute接口的一個實現(xiàn),SecurityConfig,它把配置參數(shù)保存為一個字符串。
          ?????? ConfigAttributeDefinition類是ConfigAttribute對象的一個簡單的容器,它保存了和特定請求相關(guān)的ConfigAttribute的集合。
          ?????? 當(dāng)安全攔截器收到一個安全認(rèn)證請求時,需要決定應(yīng)用哪一個配置參數(shù)。換句話說,它需要找出應(yīng)用于這個請求的ConfigAttributeDefinition對象。這個查找的過程是由ObjectDefinitionSource接口來處理的。這個接口的主要方法是public ConfigAttributeDefinition getAttributes(Object object),其中Object參數(shù)是一個安全管理對象。因為安全管理對象包含有認(rèn)證請求的詳細(xì)信息,所以O(shè)bjectDefinitionSource接口的實現(xiàn)類可以從中獲得所需的詳細(xì)信息,以查找相關(guān)的ConfigAttributeDefiniton對象。


          Acegi如何工作
          ?????? 為了說明Acegi安全系統(tǒng)如何工作,我們設(shè)想一個使用Acegi的例子。通常,一個安全系統(tǒng)需要發(fā)揮作用,它必須完成以下的工作:
          ??????1 首先,系統(tǒng)從客戶端請求中獲得Principal和Credential;
          ??????2 然后系統(tǒng)認(rèn)證Principal和Credential信息;
          ??????3 如果認(rèn)證通過,系統(tǒng)取出Principal的授權(quán)信息;
          ??????4 接下來,客戶端發(fā)起操作請求;
          ??????5 系統(tǒng)根據(jù)預(yù)先配置的參數(shù)檢查Principal對于該操作的授權(quán);
          ??????6 如果授權(quán)檢查通過則執(zhí)行操作,否則拒絕。
          ??????那么,Acegi安全系統(tǒng)是如何完成這些工作的呢?首先,我們來看看Acegi安全系統(tǒng)的認(rèn)證和授權(quán)的相關(guān)類:
          ??????安全攔截器的抽象基類,它包含有兩個管理類,AuthenticationManager和AccessDecisionManager。AuthenticationManager用于認(rèn)證ContextHolder中的Authentication對象(包含了Principal,Credential和Principal的授權(quán)信息);AccessDecissionManager則用于授權(quán)一個特定的操作。

          ??????下面來看一個MethodSecurityInterceptor的例子:
          ??????<bean id="bankManagerSecurity" 
          ???????????????????? class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
          ???????????? <property name="validateConfigAttributes">
          ????????????????????<value>true</value>
          ????????????</property>
          ????????????<property name="authenticationManager">
          ?????????????????? <ref bean="authenticationManager"/>
          ????????????</property>
          ????????????<property name="accessDecisionManager">
          ??????????????????<ref bean="accessDecisionManager"/>
          ????????????</property>
          ????????????<property name="objectDefinitionSource">
          ??????????????????<value>
          ???????????????????? net.sf.acegisecurity.context.BankManager.delete*=
          ???????????????????????????? ROLE_SUPERVISOR,RUN_AS_SERVER
          ???????????????????? net.sf.acegisecurity.context.BankManager.getBalance=
          ???????????????????????????? ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_
          ??????????????????</value>
          ????????????</property>
          ??????</bean>

          ??????上面的配置文件中,MethodSecurityInterceptor是AbstractSecurityInterceptor的一個實現(xiàn)類。它包含了兩個管理器,authenticationManager和accessDecisionManager。這兩者的配置如下:
          ??????
          <bean id="authenticationDao" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
          ?????????????? <property name="dataSource"><ref bean="dataSource"/></property>
          ??????</bean>
          ??????<bean id="daoAuthenticationProvider"
          ???????????????????? class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
          ?????????????? <property name="authenticationDao"><ref bean="authenticationDao"/></property>
          ??????</bean>
          ??????<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
          ?????????????? <property name="providers">
          ??????????????????????<list><ref bean="daoAuthenticationProvider"/></list>
          ?????????????? </property>
          ??????</bean>
          ??????<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
          ??????<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
          ?????????????? <property name="allowIfAllAbstainDecisions"><value>false</value></property>
          ?????????????? <property name="decisionVoters">
          ??????????????????????<list><ref bean="roleVoter"/></list>
          ?????????????? </property>
          ??????</bean>


          ?????? 準(zhǔn)備工作做好了,現(xiàn)在我們來看看Acegi安全系統(tǒng)是如何實現(xiàn)認(rèn)證和授權(quán)機制的。以使用HTTP BASIC認(rèn)證的應(yīng)用為例子,它包括下面的步驟:
          ?????? 1. 用戶登錄系統(tǒng),Acegi從acegisecurity.ui子系統(tǒng)的安全攔截器(如BasicProcessingFilter)中得到用戶的登錄信息(包括Principal和Credential)并放入Authentication對象,并保存在ContextHolder對象中;
          ?????? 2. 安全攔截器將Authentication對象交給AuthenticationManager進行身份認(rèn)證,如果認(rèn)證通過,返回帶有Principal授權(quán)信息的Authentication對象。此時ContextHolder對象的Authentication對象已擁有Principal的詳細(xì)信息;
          ?????? 3. 用戶登錄成功后,繼續(xù)進行業(yè)務(wù)操作;
          ?????? 4. 安全攔截器(bankManagerSecurity)收到客戶端操作請求后,將操作請求的數(shù)據(jù)包裝成安全管理對象(FilterInvocation或MethodInvocation對象);
          ?????? 5. 然后,從配置文件(ObjectDefinitionSource)中讀出相關(guān)的安全配置參數(shù)ConfigAttributeDefinition;
          ?????? 6. 接著,安全攔截器取出ContextHolder中的Authentication對象,把它傳遞給AuthenticationManager進行身份認(rèn)證,并用返回值更新ContextHolder的Authentication對象;
          ?????? 7. 將Authentication對象,ConfigAttributeDefinition對象和安全管理對象(secure Object)交給AccessDecisionManager,檢查Principal的操作授權(quán);
          ?????? 8. 如果授權(quán)檢查通過則執(zhí)行客戶端請求的操作,否則拒絕;

          AccessDecisionVoter
          ?????? 注意上節(jié)的accessDecisionManager是一個AffirmativeBased類,它對于用戶授權(quán)的投票策略是,只要通過其中的一個授權(quán)投票檢查,即可通過;它的allowIfAllAbstainDecisions屬性值是false,意思是如果所有的授權(quán)投票是都是棄權(quán),則通不過授權(quán)檢查。
          ?????? Acegi安全系統(tǒng)包括了幾個基于投票策略的AccessDecisionManager,上節(jié)的RoleVoter就是其中的一個投票策略實現(xiàn),它是AccessDecisionVoter的一個子類。AccessDecisionVoter的具體實現(xiàn)類通過投票來進行授權(quán)決策,AccessDecisionManager則根據(jù)投票結(jié)果來決定是通過授權(quán)檢查,還是拋出AccessDeniedException例外。
          ?????? AccessDecisionVoter接口共有三個方法:
          public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
          public boolean supports(ConfigAttribute attribute);
          public boolean supports(Class clazz);
          ?????? 其中的vote方法返回int返回值,它們是AccessDecisionVoter的三個靜態(tài)成員屬性:ACCESS_ABSTAIN,,ACCESS_DENIED和ACCESS_GRANTED,它們分別是棄權(quán),否決和贊成。
          ?????? Acegi安全系統(tǒng)中,使用投票策略的AccessDecisionManager共有三個具體實現(xiàn)類:AffirmativeBased、ConsensusBased和UnanimousBased。它們的投票策略是,AffirmativeBased類只需有一個投票贊成即可通過;ConsensusBased類需要大多數(shù)投票贊成即可通過;而UnanimousBased類需要所有的投票贊成才能通過。
          ?????? RoleVoter類是一個Acegi安全系統(tǒng)AccessDecisionVoter接口的實現(xiàn)。如果ConfigAttribute以ROLE_開頭,RoleVoter則進行投票。如果GrantedAuthority的getAutority方法的String返回值匹配一個或多個以ROLE_開頭的ConfigAttribute,則投票通過,否則不通過。如果沒有以ROLE_開頭的ConfigAttribute,RoleVoter則棄權(quán)。

          安全攔截器
          ??攔截器如何工作
          ??MethodInvocation攔截器
          ??FilterInvocation攔截器
          認(rèn)證
          ??認(rèn)證請求
          ??認(rèn)證管理器
          ??Authentication Provider
          授權(quán)
          ??Access Decision Manager
          ??Voting Decision Manager
          ??授權(quán)管理推薦
          ContextHolder的用戶接口
          ??用戶接口目標(biāo)
          ??HTTP會話認(rèn)證
          ??HTTP Basic認(rèn)證

          1、Log4j的概念
          ?? Log4j中有三個主要的組件,它們分別是Logger、Appender和Layout,Log4j 允許開發(fā)人員定義多個Logger,每個Logger擁有自己的名字,Logger之間通過名字來表明隸屬關(guān)系。有一個Logger稱為Root,它永遠 存在,且不能通過名字檢索或引用,可以通過Logger.getRootLogger()方法獲得,其它Logger通過 Logger.getLogger(String name)方法。
          ?? Appender則是用來指明將所有的log信息存放到什么地方,Log4j中支持多種appender,如 console、files、GUI components、NT Event Loggers等,一個Logger可以擁有多個Appender,也就是你既可以將Log信息輸出到屏幕,同時存儲到一個文件中。
          ?? Layout的作用是控制Log信息的輸出方式,也就是格式化輸出的信息。
          ?? Log4j中將要輸出的Log信息定義了5種級別,依次為DEBUG、INFO、WARN、ERROR和FATAL,當(dāng)輸出時,只有級別高過配置中規(guī)定的 級別的信息才能真正的輸出,這樣就很方便的來配置不同情況下要輸出的內(nèi)容,而不需要更改代碼,這點實在是方便啊。

          2、Log4j的配置文件
          ??雖然可以不用配置文件,而在程序中實現(xiàn)配置,但這種方法在如今的系統(tǒng)開發(fā)中顯然是不可取的,能采用配置文件的地方一定一定要用配置文件。Log4j支持兩 種格式的配置文件:XML格式和Java的property格式,本人更喜歡后者,首先看一個簡單的例子吧,如下:

           log4j.rootLogger=debug, stdout, R
          ??log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          ??log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

          ??# Pattern to output the caller's file name and line number.
          ??log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

          ??log4j.appender.R=org.apache.log4j.RollingFileAppender
          ??log4j.appender.R.File=example.log
          ??log4j.appender.R.MaxFileSize=100KB

          ??# Keep one backup file
          ??log4j.appender.R.MaxBackupIndex=1

          ??log4j.appender.R.layout=org.apache.log4j.PatternLayout
          ??log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
          ????????

          ??首先,是設(shè)置root,格式為 log4j.rootLogger=[level],appenderName, ...,其中l(wèi)evel就是設(shè)置需要輸出信息的級別,后面是appender的輸出的目的地,appenderName就是指定日志信息輸出到哪個地方。您可以同時指定多個輸出目的地。配置日志信息輸出目的地Appender,其語法為
          ??log4j.appender.appenderName = fully.qualified.name.of.appender.class
          ??log4j.appender.appenderName.option1 = value1
          ??...
          ??log4j.appender.appenderName.option = valueN
          Log4j提供的appender有以下幾種:
          ??org.apache.log4j.ConsoleAppender(控制臺)
          ??org.apache.log4j.FileAppender(文件)
          ??org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個日志文件)
          ??org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產(chǎn)生新文件)
          ??org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
          配置日志信息的格式(布局),其語法為:
          ??log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
          ??log4j.appender.appenderName.layout.option1 = value1
          ??....
          ??log4j.appender.appenderName.layout.option = valueN
          Log4j提供的layout有以下幾種:
          ??org.apache.log4j.HTMLLayout(以HTML表格形式布局),
          ??org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
          ??org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
          ??org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時間、線程、類別等等信息)

          3、Log4j在程序中的使用
          ??要在自己的類中使用Log4j,首先聲明一個靜態(tài)變量Logger logger=Logger.getLog("classname");在使用之前,用PropertyConfigurator.configure ("配置文件")配置一下,現(xiàn)在就可以使用了,用法如下:logger.debug("debug message")或者logger.info("info message"),看下面一個小例子:

           import com.foo.Bar;
          ??import org.apache.log4j.Logger;
          ??import org.apache.log4j.PropertyConfigurator;
          ??public class MyApp {
          ????static Logger logger = Logger.getLogger(MyApp.class.getName());
          ????public static void main(String[] args) {
          ??????// BasicConfigurator replaced with PropertyConfigurator.
          ??????PropertyConfigurator.configure(args[0]);
          ??????logger.info("Entering application.");
          ??????Bar bar = new Bar();
          ??????bar.doIt();
          ??????logger.info("Exiting application.");
          ????}
          ??}



          [簡介]

          對于一個典型的Web應(yīng)用,完善的認(rèn)證和授權(quán)機制是必不可少的,在SpringFramework中,Juergen Hoeller提供的范例JPetStore給了一些這方面的介紹,但還遠遠不夠,Acegi是一個專門為SpringFramework提供安全機制的 項目,全稱為Acegi Security System for Spring,當(dāng)前版本為0.5.1,就其目前提供的功能,應(yīng)該可以滿足絕大多數(shù)應(yīng)用的需求。

          本文的主要目的是希望能夠說明如何在基于Spring構(gòu)架的Web應(yīng)用中使用Acegi,而不是詳細(xì)介紹其中的每個接口、每個類。注意,即使對已經(jīng)存在的Spring應(yīng)用,通過下面介紹的步驟,也可以馬上享受到Acegi提供的認(rèn)證和授權(quán)。

          [基礎(chǔ)工作]
          在你的Web應(yīng)用的lib中添加Acegi下載包中的acegi-security.jar

          [web.xml]
          實現(xiàn)認(rèn)證和授權(quán)的最常用的方法是通過filter,Acegi亦是如此,通常Acegi需要在web.xml添加以下5個filter:

          <filter>
          ??<filter-name>Acegi Channel Processing Filter</filter-name>
          ??<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
          ??<init-param>
          ????<param-name>targetClass</param-name>
          ????<param-value>net.sf.acegisecurity.securechannel.ChannelProcessingFilter</param-value>
          ??</init-param>
          </filter>
          <filter>
          ??<filter-name>Acegi Authentication Processing Filter</filter-name>
          ??<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
          ??<init-param>
          ????<param-name>targetClass</param-name>
          ????<param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
          ??</init-param>
          </filter>
          <filter>
          ??<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
          ??<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
          ??<init-param>
          ????<param-name>targetClass</param-name>
          ????<param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value>
          ??</init-param>
          </filter>
          <filter>
          ??<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
          ??<filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
          </filter>
          <filter>
          ??<filter-name>Acegi HTTP Request Security Filter</filter-name>
          ??<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
          ??<init-param>
          ????<param-name>targetClass</param-name>
          ????<param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
          ??</init-param>
          </filter>


          最先引起迷惑的是net.sf.acegisecurity.util.FilterToBeanProxy,Acegi自己的文檔上解釋是: “What??FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the
          Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility.”,如希望深究的話,去看看源代碼應(yīng)該不難理解。

          再下來就是添加filter-mapping了:
          <filter-mapping>
          ??<filter-name>Acegi Channel Processing Filter</filter-name>
          ??<url-pattern>/*</url-pattern>
          </filter-mapping>
          <filter-mapping>
          ??<filter-name>Acegi Authentication Processing Filter</filter-name>
          ??<url-pattern>/*</url-pattern>
          </filter-mapping>
          <filter-mapping>
          ??<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
          ??<url-pattern>/*</url-pattern>
          </filter-mapping>
          <filter-mapping>
          ??<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
          ??<url-pattern>/*</url-pattern>
          </filter-mapping>
          <filter-mapping>
          ??<filter-name>Acegi HTTP Request Security Filter</filter-name>
          ??<url-pattern>/*</url-pattern>
          </filter-mapping>


          這里,需要注意以下兩點:
          1) 這幾個filter的順序是不能更改的,順序不對將無法正常工作;
          2) 如果你的應(yīng)用不需要安全傳輸,如https,則將"Acegi Channel Processing Filter"相關(guān)內(nèi)容注釋掉即可;
          3) 如果你的應(yīng)用不需要Spring提供的遠程訪問機制,如Hessian and Burlap,將"Acegi HTTP BASIC Authorization
          Filter"相關(guān)內(nèi)容注釋掉即可。

          [applicationContext.xml]
          接下來就是要添加applicationContext.xml中的內(nèi)容了,從剛才FilterToBeanFactory的解釋可以看出,真正的filter都
          在Spring的applicationContext中管理:

          1) 首先,你的數(shù)據(jù)庫中必須具有保存用戶名和密碼的table,Acegi要求table的schema必須如下:

          CREATE TABLE users (
          ????username VARCHAR(50) NOT NULL PRIMARY KEY,
          ????password VARCHAR(50) NOT NULL,
          ????enabled BIT NOT NULL
          );
          CREATE TABLE authorities (
          ????username VARCHAR(50) NOT NULL,
          ????authority VARCHAR(50) NOT NULL
          );
          CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority );
          ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users
          (username);


          2) 添加訪問你的數(shù)據(jù)庫的datasource和Acegi的jdbcDao,如下:

          <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          ??<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
          ??<property name="url"><value>${jdbc.url}</value></property>
          ??<property name="username"><value>${jdbc.username}</value></property>
          ??<property name="password"><value>${jdbc.password}</value></property>
          </bean>
          <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
          ??<property name="dataSource"><ref bean="dataSource"/></property>
          </bean>


          3) 添加DaoAuthenticationProvider:

          <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
          ??<property name="authenticationDao"><ref bean="authenticationDao"/></property>
          ??<property name="userCache"><ref bean="userCache"/></property>
          </bean>

          <bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
          ??<property name="minutesToIdle"><value>5</value></property>
          </bean>


          如果你需要對密碼加密,則在daoAuthenticationProvider中加入:<property name="passwordEncoder"><ref
          bean="passwordEncoder"/></property>,Acegi提供了幾種加密方法,詳細(xì)情況可看包
          net.sf.acegisecurity.providers.encoding

          4) 添加authenticationManager:

          <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
          ??<property name="providers">
          ????<list>
          ??????<ref bean="daoAuthenticationProvider"/>
          ????</list>
          ?? </property>
          </bean>


          5) 添加accessDecisionManager:

          <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
          ??<property name="allowIfAllAbstainDecisions">
          ????<value>false</value>
          ??</property>
          ??<property name="decisionVoters">
          ????<list><ref bean="roleVoter"/></list>
          ??</property>
          </bean>
          <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>


          6) 添加authenticationProcessingFilterEntryPoint:

          <bean id="authenticationProcessingFilterEntryPoint" 
          class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
          ??<property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
          ??<property name="forceHttps"><value>false</value></property>
          </bean>


          其中acegilogin.jsp是登陸頁面,一個最簡單的登錄頁面如下:

          <%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
          <%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %>
          <%@ page import="net.sf.acegisecurity.AuthenticationException" %>
          <html>
          ??<head>
          ????<title>Login</title>
          ??</head>

          ??<body>
          ????<h1>Login</h1>
          ????<form action="<c:url value='j_acegi_security_check'/>" method="POST">
          ??????<table>
          ????????<tr><td>User:</td><td><input type='text' name='j_username'></td></tr>
          ????????<tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
          ????????<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
          ????????<tr><td colspan='2'><input name="reset" type="reset"></td></tr>
          ??????</table>
          ????</form>
          ??</body>
          </html>


          7) 添加filterInvocationInterceptor:

          <bean id="filterInvocationInterceptor" 
          class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
          ??<property name="authenticationManager">
          ????<ref bean="authenticationManager"/>
          ??</property>
          ??<property name="accessDecisionManager">
          ????<ref bean="accessDecisionManager"/>
          ??</property>
          ??<property name="objectDefinitionSource">
          ????<value>
          ??????CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          ??????\A/sec/administrator.*\Z=ROLE_SUPERVISOR
          ??????\A/sec/user.*\Z=ROLE_TELLER
          ????</value>
          ??</property>
          </bean>


          這里請注意,要objectDefinitionSource中定義哪些頁面需要權(quán)限訪問,需要根據(jù)自己的應(yīng)用需求進行修改,我上面給出
          的定義的意思是這樣的:
          a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON意思是在比較請求路徑時全部轉(zhuǎn)換為小寫
          b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR意思是只有權(quán)限為ROLE_SUPERVISOR才能訪問/sec/administrator*的頁面
          c. \A/sec/user.*\Z=ROLE_TELLER意思是只有權(quán)限為ROLE_TELLER的用戶才能訪問/sec/user*的頁面

          8) 添加securityEnforcementFilter:

          <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
          ??<property name="filterSecurityInterceptor">
          ????<ref bean="filterInvocationInterceptor"/>
          ??</property>
          ??<property name="authenticationEntryPoint">
          ????<ref bean="authenticationProcessingFilterEntryPoint"/>
          ??</property>
          </bean>


          9) 添加authenticationProcessingFilter:

          <bean id="authenticationProcessingFilter" 
          class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
          ??<property name="authenticationManager">
          ????<ref bean="authenticationManager"/>
          ??</property>
          ??<property name="authenticationFailureUrl">
          ????<value>/loginerror.jsp</value>
          ??</property>
          ??<property name="defaultTargetUrl">
          ????<value>/</value>
          ??</property>
          ??<property name="filterProcessesUrl">
          ????<value>/j_acegi_security_check</value>
          ??</property>
          </bean>

          其中authenticationFailureUrl是認(rèn)證失敗的頁面。

          10) 如果需要一些頁面通過安全通道的話,添加下面的配置:

          <bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
          ??<property name="channelDecisionManager">
          ????<ref bean="channelDecisionManager"/>
          ??</property>
          ??<property name="filterInvocationDefinitionSource">
          ????<value>
          ??????CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          ??????\A/sec/administrator.*\Z=REQUIRES_SECURE_CHANNEL
          ??????\A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
          ??????\A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
          ??????\A.*\Z=REQUIRES_INSECURE_CHANNEL
          ????</value>
          ??</property>
          </bean>

          <bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
          ??<property name="channelProcessors">
          ????<list>
          ??????<ref bean="secureChannelProcessor"/>
          ??????<ref bean="insecureChannelProcessor"/>
          ????</list>
          ??</property>
          </bean>
          <bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
          <bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>


          [缺少了什么?]
          Acegi目前提供了兩種"secure object",分別對頁面和方法進行安全認(rèn)證管理,我這里介紹的只是利用
          FilterSecurityInterceptor對訪問頁面的權(quán)限控制,除此之外,Acegi還提供了另外一個Interceptor――
          MethodSecurityInterceptor,它結(jié)合runAsManager可實現(xiàn)對對象中的方法的權(quán)限控制,使用方法可參看Acegi自帶的文檔
          和contact范例。

          [最后要說的]
          本來以為只是說明如何使用Acegi而已,應(yīng)該非常簡單,但真正寫起來才發(fā)現(xiàn)想要條理清楚的理順?biāo)行枰腷ean還是很
          困難的,但愿我沒有遺漏太多東西,如果我的文章有什么遺漏或錯誤的話,還請參看Acegi自帶的quick-start范例,但請
          注意,這個范例是不能直接拿來用的。
          分析和學(xué)習(xí)Spring中的jpetstore用戶管理
          ??存在用戶的系統(tǒng),必然需要用戶的登錄和認(rèn)證,今天就通過分析Spring中自帶的jpetstore的例子來學(xué)習(xí)一下如何實現(xiàn)在Spring構(gòu)架的系統(tǒng)中用戶登錄。
          1、首先從注冊用戶開始,先看看jpetstore-servlet.xml中關(guān)于注冊用戶的bean定義,從定義命名中就可以看出下面這段就是注冊用戶的:
          ??
          <bean name="/shop/newAccount.do" class="org.springframework.samples.jpetstore.web.spring.AccountFormController">
          ????<property name="petStore"><ref bean="petStore"/></property>
          ????<property name="validator"><ref bean="accountValidator"/></property>
          ????<property name="successView"><value>index</value></property>
          ??</bean>

          1). formView呢?從AccountFormController的構(gòu)造函數(shù)中得到,原來為EditAccountForm;??
          2). EditoAccountForm.jsp中顯得非常亂,其實沒有多少難理解的地方,最主要的是這個form既是添加新用戶的,又是編輯用戶信息的,所以顯得有點亂糟糟的。
          2、添加好了新用戶,接下來看看如何登錄,在jpetstore-servlet中發(fā)現(xiàn)這兩個相關(guān)bean定義,如下:
          ??
          <bean name="/shop/signon.do" class="org.springframework.samples.jpetstore.web.spring.SignonController">
          ????<property name="petStore"><ref bean="petStore"/></property>
          ??</bean>
          ??<bean name="/shop/signonForm.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
          ????<property name="viewName"><value>SignonForm</value></property>
          ??</bean>

          1). 第二個bean是在運行時用戶輸入用戶名和密碼的form,叫做SignonForm,對于這個 ParameterizableViewController,用文檔里的話說這是最簡單的Controller,其作用就是在運行中指向 Controller而不是直接指向jsp文件,僅此而已。
          2). SignonForm.jsp,里面就是一個簡單的form,其action就是第一個bean,即/shop/signon.do,最需要注意的是 signonForwardAction,其主要作用是forward到需要輸入用戶名和密碼的那個頁面上去,這個變量哪里來的呢?看看下面:
          ??
          <bean id="secureHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          ????<property name="interceptors">
          ??????<list>
          ????????<ref bean="signonInterceptor"/>
          ??????</list>
          ????</property>
          ????<property name="urlMap">
          ??????<map>
          ????????<entry key="/shop/editAccount.do"><ref local="secure_editAccount"/></entry>
          ????????<entry key="/shop/listOrders.do"><ref local="secure_listOrders"/></entry>
          ????????<entry key="/shop/newOrder.do"><ref local="secure_newOrder"/></entry>
          ????????<entry key="/shop/viewOrder.do"><ref local="secure_viewOrder"/></entry>
          ??????</map>
          ????</property>
          ??</bean>

          ??原來,上面的signonInterceptor實現(xiàn)了preHandle,因此在請求上面的map頁面時,首先要經(jīng)過這個Interceptor,看看 SignonInterceptor的源碼,原來在其中為signon.jsp賦予一個signonForwardAction對象,呵呵,總算明白了。
          3). 接下來去學(xué)習(xí)一下SignonController,其主體部分中可以看出,首先取出用戶輸入的username和password,然后到數(shù)據(jù)庫中驗證 有沒有這個用戶,如果沒有這個用戶,返回各錯誤頁面;如果成功,首先生成一個UserSession對象,在request的session加入這個 userSession,注意這部分代碼中給出了PagedListHolder分頁的簡單使用方法,關(guān)于分頁顯示,以后再學(xué)習(xí)吧。
          3、登錄成功后,就可以根據(jù)不同的用戶設(shè)施不同的行為了,取得用戶信息,無非就是從session取出userSession即可。
          posted on 2006-12-27 23:20 海思 閱讀(226) 評論(0)  編輯  收藏 所屬分類: Acegi

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 葫芦岛市| 龙陵县| 临猗县| 保靖县| 沙坪坝区| 横峰县| 广南县| 淮安市| 宁都县| 咸丰县| 兴义市| 曲麻莱县| 临夏市| 兰西县| 延吉市| 连云港市| 长泰县| 灵石县| 通州市| 泊头市| 南部县| 大余县| 浦县| 大新县| 泰来县| 吴堡县| 昭平县| 南皮县| 上蔡县| 新巴尔虎右旗| 扶余县| 双柏县| 湛江市| 行唐县| 石城县| 通城县| 台中县| 荃湾区| 长丰县| 辽源市| 西平县|