<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    tangtb

    Hadoop,SpringMVC,ExtJs,Struts2,Spring,SpringSecurity,Hibernate,Struts
    posts - 25, comments - 88, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
     

    Spring Security學(xué)習(xí)總結(jié)一


    在認(rèn)識Spring Security之前,所有的權(quán)限驗(yàn)證邏輯都混雜在業(yè)務(wù)邏輯中,用戶的每個(gè)操作以前可能都需要對用戶是否有進(jìn)行該項(xiàng) 操作的權(quán)限進(jìn)行判斷,來達(dá)到認(rèn)證授權(quán)的目的。類似這樣的權(quán)限驗(yàn)證邏輯代碼被分散在系統(tǒng)的許多地方,難以維護(hù)。AOP(Aspect Oriented Programming)和Spring Security為我們的應(yīng)用程序很好的解決了此類問題,正如系統(tǒng)日志,事務(wù)管理等這些系統(tǒng)級的服務(wù)一樣,我們應(yīng) 該將它作為系統(tǒng)一個(gè)單獨(dú)的”切面”進(jìn)行管理,以達(dá)到業(yè)務(wù)邏輯與系統(tǒng)級的服務(wù)真正分離的目的,Spring Security將系統(tǒng)的安全邏輯 從業(yè)務(wù)中分離出來。

    本文代碼運(yùn)行環(huán)境:
     

    JDK6.0

        spring-framework-2.5.4

        spring-security-2.0.0

        JavaEE5

    Web容器:

    Apache Tomcat6.0

    IDE工具:

    Eclipse3.3+MyEclipse6.5

    操作系統(tǒng):

    Linux(Fedora 8)

        這只是我個(gè)人的學(xué)習(xí)總結(jié)而已,還請高手們指出本文的不足之處。

    一  Spring Security 簡介

    這里提到的Spring Security也就是被大家廣為熟悉的Acegi Security,2007年底Acegi Security正式成為Spring Portfolio項(xiàng)目,并更名為Spring Security。Spring Security是一個(gè)能夠?yàn)?/span>基于Spring的企業(yè)應(yīng)用系統(tǒng)提供描述性安全訪問控制解決方案的安全框架。 它提供了一可以在Spring應(yīng)用上下文中配置的Bean,充分利用了Spring IoC(依注入,也稱控制反轉(zhuǎn))和AOP(面向切面程)功能,為應(yīng)用系統(tǒng)提供聲明式的安全訪問控制功能,減少了為企業(yè)系統(tǒng)安全控制編寫大量重復(fù)代碼的工作。

    通過在許多項(xiàng)目中實(shí)踐應(yīng)用以及社區(qū)的貢獻(xiàn),如今的Spring Security已經(jīng)成為Spring Framework下最成熟的安全系統(tǒng),它為我們提供了強(qiáng)大而靈活的企業(yè)級安全服務(wù),如:

    Ø         認(rèn)證授權(quán)機(jī)制

    Ø         Web資源訪問控制

    Ø         業(yè)務(wù)方法調(diào)用訪問控制

    Ø         領(lǐng)域?qū)ο笤L問控制Access Control ListACL

    Ø         單點(diǎn)登錄(Central Authentication Service

    Ø         X509認(rèn)證

    Ø         信道安全(Channel Security)管理等功能

    當(dāng)保護(hù)Web資源時(shí),Spring Security使用Servlet 過濾器來攔截Http請求進(jìn)行身份驗(yàn)證并強(qiáng)制安全性,以 確保WEB資源被安全的訪問。如下圖是Spring Security的主要組件圖(摘自《Spring in Action》):



    1 Spring Security的基本組件

    無論是保護(hù)WEB資源還是保護(hù)業(yè)務(wù)方法或者領(lǐng)域?qū)ο螅?/span>Spring Security都的通過上圖中的組件來完成 的。本文主要闡述如何使用Spring Security對WEB應(yīng)用程序的資源進(jìn)行安全訪問控制,并通過一個(gè)簡單的 實(shí)例來對Spring Security提供的各種過濾器的功能和配置方法進(jìn)行描述。

    二  保護(hù)Web資源

    Spring Security提供了很多的過濾器,它們攔截Servlet請求,并將這些請求轉(zhuǎn)交給認(rèn)證處理過濾器和訪問決策過濾器進(jìn)行處理,并強(qiáng)制安全性,認(rèn)證用戶身份和用戶權(quán)限以達(dá)到保護(hù)Web資源的目的。對于Web資源我們大約可以只用6個(gè)過濾器來保護(hù)我們的應(yīng)用系統(tǒng),下表列出了這些安全過濾器的名稱作用以及它們在系統(tǒng)中的執(zhí)行順序:

      

                 

    通道處理過濾器

    確保請求是在安全通道(HTTP和HTTPS)之上傳輸?shù)?/span>

    認(rèn)證處理過濾器

    接受認(rèn)證請求,并將它們轉(zhuǎn)交給認(rèn)證管理器進(jìn)行身份驗(yàn)證

    CAS處理過濾器

    接受CAS服務(wù)票據(jù),驗(yàn)證Yale CAS(單點(diǎn)登錄)是否已經(jīng)對用戶進(jìn)行了認(rèn)證

    HTTP基本授權(quán)過濾器

    處理使用HTTP基本認(rèn)證的身份驗(yàn)證請求

    集成過濾器

    處理認(rèn)證信息在請求間的存儲(chǔ)(比如在HTTP會(huì)話中)

    安全強(qiáng)制過濾器

    確保用戶己經(jīng)認(rèn)證,并且滿足訪問一個(gè)受保護(hù)Web資源的權(quán)限需求

    接下來,通過一個(gè)實(shí)例來說明它們的具體使用方法和如何在Spring中進(jìn)行配置。

    1  建立Spring Security項(xiàng)目

    首先在MyEclipse中創(chuàng)建一個(gè)Web Project,并使用MyEclipse工具導(dǎo)入Spring項(xiàng)目的依賴JAR包,并生成默認(rèn)的,這里暫時(shí)不會(huì)用到這個(gè)文件,本文只是通過一個(gè)簡單的實(shí)例來說明如何配置使用Spring Security,不會(huì)涉及到數(shù)據(jù)庫,而是使用一個(gè)用戶屬性(users.properties)文件來保存用戶信息(包括用戶名,密碼及相應(yīng)的權(quán)限),但在實(shí)際的項(xiàng)目中,我們很少會(huì)這樣做,而是應(yīng)該把用戶信息存在數(shù)據(jù)庫中,下一篇文章中將會(huì)詳細(xì)介紹并用到這個(gè)文件來配置Hibernate,這里我們保留它。

    現(xiàn)在還需要為項(xiàng)目導(dǎo)入Spring SecurityJAR包,它沒有包括在Spring Framework中,你可以從http://www.springframework.org/download/下載,并將spring-security-core-2.0.0.jar(這是核心代碼庫)和spring-security-core-tiger-2.0.0.jar(和annotation有關(guān)的,比如使用注解對方法進(jìn)行安全訪問控制,在下一篇中會(huì)用到)拷貝到項(xiàng)目的lib目錄下,其中也包括兩個(gè)實(shí)例(tutorial和contacts),并且兩個(gè)實(shí)例中都包括了如何使用Spring 2.0的命名空間來配置Spring Security,無論你對Spring 2.0命名空間的使用是否了解,它將使我們的配置文件大大縮短,簡化開發(fā),提高生產(chǎn)效率。到此,我們的Spring Security項(xiàng)目就建好了,項(xiàng)目目錄結(jié)構(gòu)如下圖所示:


    項(xiàng)目目錄結(jié)構(gòu)

    2 配置web.xml

    Spring Security使用一組過濾器鏈來對用戶進(jìn)行身份驗(yàn)證和授權(quán)。首先,在web.xml文件中添加FilterToBeanProxy過濾器配置:

     1 <filter>   
     2       <filter-name>springSecurityFilterChain</filter-name>
     3      <filter-class>
     4         org.springframework.security.util.FilterToBeanProxy
     5      </filter-class>
     6      <init-param>       
     7           <
    param-name>targetClass</param-name>
     8          <param-value>           
     9               org.springframework.security.util.FilterChainProxy
    10          </param-value>
    11       </init-param>
    12 </filter>
    13

    org.springframework.security.util.FilterToBeanProxy實(shí)現(xiàn)了Filter接口,它通過調(diào)用WebapplicationContextUtils類的getWebApplicationnContext(servletContext)方法來獲取Spring的應(yīng)用上下文句柄,并通過getBean(beanName)方法來獲取Spring受管Bean的對象,即這里targetClass參數(shù)配置的Bean,并通過調(diào)用FilterChain
    Proxy
    init()方法來啟動(dòng)Spring Security過濾器鏈進(jìn)行各種身份驗(yàn)證和授權(quán)服務(wù)(FilterChainProxy類也是實(shí)現(xiàn)了Filter接口),從而將過濾功能委托給Spring的FilterChainProxy受管Bean(它維護(hù)著一個(gè)處理驗(yàn)證和授權(quán)的過濾器 列表,列表中的過濾器按照一定的順序執(zhí)行并完成認(rèn)證過程),這樣即簡化了web.xml文件的配置,又能充分利用 Spring的IoC功能來完成這些過濾器執(zhí)行所需要的其它資源的注入。

    當(dāng)用戶發(fā)出請求,過濾器需要根據(jù)web.xml配置的請求映射地址來攔截用戶請求,這時(shí)Spring Security開始工作,它會(huì)驗(yàn)證你的身份以及當(dāng)前請求的資源是否與你擁有的權(quán)限相符,從而達(dá)到保護(hù)Web資源的功能,下面是本例所要過濾的用戶請求地址:

     1 <filter-mapping>
     2 
     3        <filter-name>springSecurityFilterChain</filter-name>
     4 
     5        <url-pattern>/j_spring_security_check</url-pattern>
     6 
     7     </filter-mapping>
     8 
     9     <filter-mapping>
    10 
    11        <filter-name>springSecurityFilterChain</filter-name>
    12 
    13        <url-pattern>/*</url-pattern>
    14 
    15 </filter-mapping>

    提示:
    /j_spring_security_check是Spring Security默認(rèn)的進(jìn)行表單驗(yàn)證的過濾地址,你也可以修改為別的名稱,但是需要和
    applicationContext-security.xml中相對應(yīng),當(dāng)然還會(huì)涉及到其它一些默認(rèn)值(可能是一個(gè)成員變量,也可能是別的請
    求地址),在下文我們將看到,建議你在閱讀此文的同時(shí),應(yīng)該參照Spring Security項(xiàng)目的源代碼,便于你更好的理解。
     

    配置applicationContext-security.xml

    3.1 FilterChainProxy過濾器鏈

    FilterChainProxy會(huì)按順序來調(diào)用一組filter,使這些filter即能完成驗(yàn)證授權(quán)的本質(zhì)工作,又能享用Spring Ioc的功能來方便的得到其它依賴的資源。FilterChainProxy配置如下:

     1 <bean id="filterChainProxy"   
            class
    ="org.springframework.security.util.FilterChainProxy">
     2      <property name="filterInvocationDefinitionSource">
     3         <value><![CDATA[         
                    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
     4              PATTERN_TYPE_APACHE_ANT         
                    /**=httpSessionContextIntegrationFilter,logoutFilter,
     5              authenticationProcessingFilter,securityContextHolderAwareRequestFilter,
     6              rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,
     7              filterSecurityInterceptor 
     8         ]]></value>
     9      </property>
    10 </bean>

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 定義URL在匹配之前必須先轉(zhuǎn)為小寫,PATTERN_TYPE_APACHE_ANT 定義了使用Apache ant的匹配模式,/**定義的將等號后面的過濾器應(yīng)用在那些URL上,這里使用全部URL過濾,每個(gè)過濾器之間都適用逗號分隔,它們按照一定的順序排列。

    提示:
    特別需要注意的是,即使你配置了系統(tǒng)提供的所有過濾器,這個(gè)過濾器鏈會(huì)很長,但是千萬不要使用換行,否則它們不會(huì)正常工作,
    容器甚至不能正常啟動(dòng)。
     

    下面根據(jù)FilterChainProxy的配置來介紹各個(gè)過濾器的配置,各個(gè)過濾器的執(zhí)行順序如以上配置。

    首先是通道處理過濾器,如果你需要使用HTTPS,這里我們就使用HTTP進(jìn)行傳輸,所以不需要配置通道處理過濾器,然后是集成過濾器,配置如下:

    1 <bean id="httpSessionContextIntegrationFilter"
    2 
    3 class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>

    httpSessionContextIntegrationFilter集成過濾器的一個(gè)實(shí)現(xiàn),在用戶的一個(gè)請求過程中,用戶的認(rèn)證信息通過SecurityContextHolder(使用ThreadLoacl實(shí)現(xiàn))進(jìn)行傳遞的,所有的過濾器都是通過SecurityContextHolder來獲取用戶的認(rèn)證信息,從而在一次請求中所有過濾器都能共享Authentication(認(rèn)證),減少了HttpRequest參數(shù)的傳送,下面的代碼是從安全上下文的獲取Authentication對象的方法:

    1 SecurityContext context = SecurityContextHolder.getContext();
    2 
    3 Authentication authentication = context.getAuthentication();

    但是,ThreadLoacl不能跨越多個(gè)請求存在,所以,集成過濾器在請求開始時(shí)從Http會(huì)話中取出用戶認(rèn)證信息并創(chuàng)建一個(gè)SecurityContextHolder將Authentication對象保存在其中,在請求結(jié)束之后,在從SecurityContextHolder中獲取Authentication對象并將其放回Http會(huì)話中,共下次請求使用,從而達(dá)到了跨越多個(gè)請求的目的。集成過濾器還有其它的實(shí)現(xiàn),可以參考相關(guān)文檔。

    提示:
    集成過濾器必須在其它過濾器之前被使用。
     

    logoutFilter(退出過濾器) ,退出登錄操作:

     1 <bean id="logoutFilter"
     2 
     3     class="org.springframework.security.ui.logout.LogoutFilter">
     4 
     5     <constructor-arg value="/index.jsp"/>
     6 
     7     <constructor-arg>
     8 
     9        <list>
    10 
    11            <!-- 實(shí)現(xiàn)了LogoutHandler接口(logout方法) -->
    12 
    13            <ref bean="rememberMeServices"/>
    14 
    15            <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler"/>
    16 
    17        </list>
    18 
    19     </constructor-arg>
    20 
    21 </bean>

    LogoutFilter的構(gòu)造函數(shù)需要兩個(gè)參數(shù),第一個(gè)是退出系統(tǒng)后系統(tǒng)跳轉(zhuǎn)到的URL,第二個(gè)是一個(gè)LogoutHandler類型的數(shù)組,這個(gè)數(shù)組里的對象都實(shí)現(xiàn)了LogoutHandler接口,并實(shí)現(xiàn)了它的logout方法,用戶在發(fā)送退出請求后,會(huì)一次執(zhí)行LogoutHandler數(shù)組的對象并調(diào)用它們的 logout方法進(jìn)行一些后續(xù)的清理操作,主要是從SecurityContextHolder對象中清楚所有用戶的認(rèn)證信息(Authentication對象),將用戶的會(huì)話對象設(shè)為無效,這些都時(shí)由SecurityContextLogoutHandler來完成。LogoutFilter還會(huì)清除Cookie記錄,它由另外一個(gè)Bean來完成(RememberMeServices)。

    <ref bean="rememberMeServices"/>標(biāo)記指向了我們另外配置的一個(gè)Bean:

    1 <bean id="rememberMeServices"    
            class
    ="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices"
    2     p:key="springsecurity"
    3     p:userDetailsService-ref="userDetailsService"/>

    TokenBasedRememberMeServices繼承自系統(tǒng)的AbstractRememberMeServices抽象類(實(shí)現(xiàn)了RememberMeServices和 LogoutHandler兩個(gè)接口), RememberMeServices接口的loginSuccess方法負(fù)責(zé)在用戶成功登錄之后將用戶的認(rèn)證信息存入Cookie中,這個(gè)類在后續(xù)的過濾器執(zhí)行過程中也會(huì)被用到。

    另一個(gè)userDetailsService屬性也是指向了我們配置的Bean, 它負(fù)責(zé)從數(shù)據(jù)庫中讀取用戶的信息,這個(gè)類的詳細(xì)配置將在后面的部分詳細(xì)介紹,這里只是簡單的認(rèn)識一下。

    過濾器鏈的下個(gè)配置的過濾器是authenticationProcessingFilter(認(rèn)證過程過濾器),我們使用它來處理表單認(rèn)證,當(dāng)接受到與filterProcessesUrl所定義相同的請求時(shí)它開始工作

     1 <bean id="authenticationProcessingFilter"
     2 
     3     class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"
     4 
     5     p:authenticationManager-ref="authenticationManager"
     6     p:authenticationFailureUrl="/login.jsp?login_error=1"
     7     p:defaultTargetUrl="/default.jsp"
     8     p:filterProcessesUrl="/j_spring_security_check"
     9     p:rememberMeServices-ref="rememberMeServices"/>

    下面列出了認(rèn)證過程過濾器配置中各個(gè)屬性的功能:

        1.authenticationManager     認(rèn)證管理器

        2.authenticationFailureUrl 定義登錄失敗時(shí)轉(zhuǎn)向的頁面

        3.defaultTargetUrl         定義登錄成功時(shí)轉(zhuǎn)向的頁面

        4.filterProcessesUrl        定義登錄請求的地址(在web.xml中配置過)

        5.rememberMeServices        在驗(yàn)證成功后添加cookie信息

    這里也用到了rememberMeServices,如果用戶認(rèn)證成功,將調(diào)用RememberMeServices的loginSuccess方法將用戶認(rèn)證信息寫入Cookie中,這里也可以看到使用IoC的好處。

    決定用戶是否有權(quán)限訪問受保護(hù)資源的第一步就是要確定用戶的身份,最常用的方式就是用戶提供一個(gè)用戶名和密碼以確認(rèn)用戶的身份是否合法,這一步就是由認(rèn)證過程過濾器調(diào)用authenticationManager(認(rèn)證管理器)來完成的。org.springframework.security.AuthenticationManager接口定義了一個(gè)authenticate方法,它使用Authentication作為入口參數(shù)(只包含用戶名和密碼),并在驗(yàn)證成功后返回一個(gè)完整的Authentication對象(包含用戶的權(quán)限信息GrantedAuthority數(shù)組對象),authenticationProcessingFilter(認(rèn)證過程過濾器)會(huì)將這個(gè)完整的Authentication對象存入SecurityContext中,如果認(rèn)證失敗會(huì)拋出一個(gè)AuthenticationException并跳轉(zhuǎn)到authenticationFailureUrl 定義的URL。認(rèn)證管理其配置如下:

     1 <bean id="authenticationManager"
     2 
     3 class="org.springframework.security.providers.ProviderManager"
     4  p:sessionController-ref="concurrentSessionController">
     5     <property name="providers">
     6        <list>
     7            <ref bean="daoAuthenticationProvider"/>
     8            <bean
     9 
    10 class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider"
    11               p:key="springsecurity"/>
    12            <bean
    13 
    14 class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider"
    15               p:key="springsecurity"/>
    16        </list>
    17     </property>  
    18 </bean>

    正如在配置中看到的一樣,系統(tǒng)使用org.springframework.security.providers.ProviderManager(提供者管理器)類作為認(rèn)證管理器的一個(gè)實(shí)現(xiàn),事實(shí)上這個(gè)類是繼承自實(shí)現(xiàn)了AuthenticationManager接口的 AbstractAuthenticationManager類。需要注意的是ProviderManager(提供者管理器)自己并不實(shí)現(xiàn)身份驗(yàn)證,而是把這項(xiàng)工作交給了多個(gè)認(rèn)證提供者(提供者集合)或者說的多個(gè)認(rèn)證來源。

    提示:
    Spring Security為我們提供的所有認(rèn)證提供者實(shí)現(xiàn)都是org.springframework.security.providers .AuthenticationProvider
    接口的實(shí)現(xiàn)類,它們都實(shí)現(xiàn)了此接口的authenticate方法,如果你正在看源代碼,會(huì)發(fā)現(xiàn)這個(gè)authenticate方法事實(shí)上和Authe
    nticationManager(認(rèn)證管理器)接口的authenticate方法完全一樣。
     

    providers屬性定義了提供者管理器的集合,ProviderManager(提供者管理器)逐一遍歷這個(gè)認(rèn)證提供者的集合并調(diào)用提供者的authenticate方法,如果一個(gè)提供者認(rèn)證失敗會(huì)嘗試另外一個(gè)提供者直到某一個(gè)認(rèn)證提供者能夠成功的驗(yàn)證該用戶的身份,以保證獲取不同來源的身份認(rèn)證。下面表格列出了系統(tǒng)提供的一些認(rèn)證提供者:

         

                

    DaoAuthenticationProvider

    從數(shù)據(jù)庫中讀取用戶信息驗(yàn)證身份

    AnonymousAuthenticationProvider

    匿名用戶身份認(rèn)證

    RememberMeAuthenticationProvider

    已存cookie中的用戶信息身份認(rèn)證

    AuthByAdapterProvider

    使用容器的適配器驗(yàn)證身份

    CasAuthenticationProvider

    根據(jù)Yale中心認(rèn)證服務(wù)驗(yàn)證身份, 用于實(shí)現(xiàn)單點(diǎn)登陸

    JaasAuthenticationProvider

    JASS登陸配置中獲取用戶信息驗(yàn)證身份

    RemoteAuthenticationProvider

    根據(jù)遠(yuǎn)程服務(wù)驗(yàn)證用戶身份

    RunAsImplAuthenticationProvider

    對身份已被管理器替換的用戶進(jìn)行驗(yàn)證

    X509AuthenticationProvider

    X509認(rèn)證中獲取用戶信息驗(yàn)證身份

    TestingAuthenticationProvider

    單元測試時(shí)使用





















        從上面的表中可以看出,系統(tǒng)為我們提供了不同的認(rèn)證提供者,
    每個(gè)認(rèn)證提供者會(huì)對自己指定的證明信息進(jìn)行認(rèn)證,如DaoAuthenticationProvider僅對UsernamePasswordAuthenticationToken這個(gè)證明信息進(jìn)行認(rèn)證。

    在實(shí)際項(xiàng)目中,用戶的身份和權(quán)限信息可能存儲(chǔ)在不同的安全系統(tǒng)中(如數(shù)據(jù)庫,LDAP服務(wù)器CA中心)。
    作為程序員,我們可以根據(jù)需要選擇不同的AuthenticationProvider(認(rèn)證提供者)來對自己的系統(tǒng)提供認(rèn)證 服務(wù)。

    這里我們著重介紹DaoAuthenticationProvider,它從數(shù)據(jù)庫中讀取用戶信息驗(yàn)證身份,配置如下:

    1 <bean id="daoAuthenticationProvider" 
            class
    ="org.springframework.security.providers.dao.DaoAuthenticationProvider"
    2     p:passwordEncoder-ref="passwordEncoder"
    3     p:userDetailsService-ref="userDetailsService"/>
    4 <bean id="passwordEncoder"
    5     class="org.springframework.security.providers.encoding.Md5PasswordEncoder"/>

    還記得前面配置的RememberMeServices嗎?它也有一個(gè)和DaoAuthenticationProvider同樣的屬性userDetailsService,這是系統(tǒng)提供的一個(gè)接口(org.springframework.security.userdetails.UserDetailsService),在這里我們把它單獨(dú)提出來進(jìn)行介紹。

    首先我們需要了解Spring Security為我們提供的另外一個(gè)重要的組件,org.springframework.security.userdetails .UserDetails接口,它代表一個(gè)應(yīng)用系統(tǒng)的用戶,該接口定義與用戶安全信息相關(guān)的方法:

    String getUsername():獲取用戶名; 

    String getPassword():獲取密碼; 

    boolean isAccountNonExpired():用戶帳號是否過期; 

    boolean isAccountNonLocked():用戶帳號是否鎖定; 

    boolean isCredentialsNonExpired():用戶的憑證是否過期; 

    boolean isEnabled():用戶是否處于激活狀態(tài)。

    當(dāng)以上任何一個(gè)判斷用戶狀態(tài)的方法都返回false時(shí),用戶憑證就被視為無效。UserDetails接口還定義了獲取用戶權(quán)限信息的getAuthorities()方法,該方法返回一個(gè)GrantedAuthority[]數(shù)組對象,GrantedAuthority是用戶權(quán)限信息對象,這個(gè)對象中定義了一個(gè)獲取用戶權(quán)限描述信息的getAuthority()方法。

    UserDetails即可從數(shù)據(jù)庫中返回,也可以從其它如LDAP中返回,這取決與你的系統(tǒng)中使用什么來存儲(chǔ)用戶信息和權(quán)限以及相應(yīng)的認(rèn)證提供者。這里我們只重點(diǎn)介紹DaoAuthenticationProvider(從數(shù)據(jù)庫中獲取用戶認(rèn)證信息的提供者),本人水平有限,在項(xiàng)目中還沒有機(jī)會(huì)用到其它提供者。說到這里,這個(gè)封裝了用戶詳細(xì)信息的UserDetails該從哪兒獲取呢?這就是我們接下來要介紹的UserDetailsService接口,這個(gè)接口中只定義了唯一的UserDetails loadUserByUsername(String username)方法,它通過用戶名來獲取整個(gè)UserDetails對
    象。

    看到這里你可能會(huì)有些糊涂,因?yàn)榍懊嫣岬降?/span>Authentication對象中也存放了用戶的認(rèn)證信息,需要注意Authentication對象才是Spring Security使用的進(jìn)行安全訪問控制用戶信息安全對象。實(shí)際上,Authentication對象有未認(rèn)證和已認(rèn)證兩種狀態(tài),在作為參數(shù)傳入認(rèn)證管理器(AuthenticationManager)的authenticate方法時(shí),是一個(gè)未認(rèn)證的對象,它從客戶端獲取用戶的身份信息(如用戶名,密碼),可以是從一個(gè)登錄頁面,也可以從Cookie中獲取,并由系統(tǒng)自動(dòng)構(gòu)造成一個(gè)Authentication對象。而這里提到的UserDetails代表一個(gè)用戶安全信息的源(從數(shù)據(jù)庫,LDAP服務(wù)器,CA中心返回),Spring Security要做的就是將這個(gè)未認(rèn)證的Authentication對象和UserDetails進(jìn)行匹配,成功后將UserDetails中的用戶權(quán)限信息拷貝到Authentication中組成一個(gè)完整的Authentication對象,共其它組件共享。

    這樣,我們就可以在系統(tǒng)中獲取用戶的相關(guān)信息了,需要使用到Authentication對象定義的Object getPrincipal()方法,這個(gè)方法返回一個(gè)Object類型的對象,通??梢詫⑺D(zhuǎn)換為UserDetails,從而可以獲取用戶名,密碼以及權(quán)限等信息。代碼如下:

    1 UserDetails details = (UserDetails)authentication.getPrincipal();
    2 
    3 GrantedAuthority[] authority = details.getAuthorities();

    前面介紹了DaoAuthenticationProvider,它可以從數(shù)據(jù)庫中讀取用戶信息,同樣也可以從一個(gè)用戶屬性文件中讀取,下一篇文章中我們在介紹如何從數(shù)據(jù)庫中讀取用戶信息,當(dāng)然還會(huì)涉及到更深入的東西,比如根據(jù)自己系統(tǒng)的需要自定義UserDetails和UserDetailsService,這個(gè)只是讓你對整個(gè)系統(tǒng)有個(gè)簡單的了解,所以我們使用用戶屬性文件(users.properties)來存儲(chǔ)用戶信息:

    1 admin=admin,ROLE_SUPERVISOR
    2 
    3 user1=user1,ROLE_USER
    4 
    5 user2=user2,ROLE_USER
    6 
    7 user3=user3,disabled,ROLE_USER

        配置userDetailsService

    1 <bean id="userDetailsService"
    2 
    3 class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
    4      <property name="userProperties">
    5         <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean"
    6           p:location
    ="/WEB-INF/users.properties"/>
    7      </property>
    8 </bean>

    InMemoryDaoImpl類是UserDetailsService接口的一個(gè)實(shí)現(xiàn),它從屬性文件里讀取用戶信息,Spring Security使用一個(gè)屬性編輯器將用戶信息為我們組織成一個(gè)org.springframework.security.userdetails.memory.UserMap類的對象,我們也可以直接為它提供一個(gè)用戶權(quán)限信息的列表,詳見applicationContext-security.xml配置文件。

    UserMap字符串的每一行都用鍵值對的形式表示,前面是用戶名,然后是等號,后面是賦予該用戶的密碼/權(quán)限等信息,它們使用逗號隔開。比如:

    1 admin=admin,ROLE_SUPERVISOR

    定義了一個(gè)名為admin的用戶登錄密碼為admin,該用戶擁有ROLE_SUPERVISOR權(quán)限,再如users.properties文件中配置的名為user3的用戶登錄密碼為user3,該用戶擁有ROLE_USER權(quán)限,disabled定義該用戶不可用,為被激活(UserDetails isEnabled方法)。

    即使是系統(tǒng)的開發(fā)者或者說是最終用戶,都不應(yīng)該看到系統(tǒng)中有明文的密碼。所以,Spring Security考慮的還是很周到的,為我們提供的密碼加密的功能。正如你在Dao認(rèn)證提供者(DaoAuthenticationProvider)中看到的,passwordEncoder屬性配置的就是一個(gè)密碼加密程序(密碼編碼器)。這里我們使用MD5加密,可以看
    配置文件中的scott用戶,你還能看出他的密碼是什么嗎?當(dāng)然這里只是演示功能,其它用戶還是沒有改變, 你可以自己試試。系統(tǒng)為我們提供了一些常用的密碼編碼器(這些編碼器都位于org.springframework.secu rity.providers.encoding包下):

    PlaintextPasswordEncoder(默認(rèn))——不對密碼進(jìn)行編碼,直接返回未經(jīng)改變的密碼;

    Md4PasswordEncoder ——對密碼進(jìn)行消息摘要(MD4)編碼;

    Md5PasswordEncoder ——對密碼進(jìn)行消息摘要(MD5)編碼;

    ShaPasswordEncoder ——對密碼進(jìn)行安全哈希算法(SHA)編碼。

        你可以根據(jù)需要選擇合適的密碼編碼器,你也可以設(shè)編碼器的子源(salt source)。一個(gè)子源為編碼提供(salt),或者稱編碼的密鑰,這里不再贅述。

    這里附加介紹了不少東西,希望你還沒有忘記在AuthenticationManager認(rèn)證管理器)中還配置了一個(gè)名為sessionController的Bean,這個(gè)Bean可以阻止用戶在進(jìn)行了一次成功登錄以后在進(jìn)行一次成功的登錄。在 applicationContext-security.xml配置文件添加sessionController的配置:

    1 <bean id="concurrentSessionController"
    2 
    3 class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl"
    4     p:maximumSessions="1"
    5     p:exceptionIfMaximumExceeded="true"
    6     p:sessionRegistry-ref="sessionRegistry"/>
    7 <bean id="sessionRegistry"
    8 
    9 class="org.springframework.security.concurrent.SessionRegistryImpl"/>

    maximumSessions屬性配置了只允許同一個(gè)用戶登錄系統(tǒng)一次,exceptionIfMaximumExceeded屬性配置了在進(jìn)行第二次登錄是是否讓第一次登錄失效。這里設(shè)置為true不允許第二次登錄。要讓此功能生效,我們還 需要在web.xml文件中添加一個(gè)監(jiān)聽器,以讓Spring Security能獲取Session的生命周期事件,配置如下:

    1 <listener>
    2      <listener-class>
    3         org.springframework.security.ui.session.HttpSessionEventPublisher
    4      </listener-class>
    5 </listener>

    HttpSessionEventPublisher類實(shí)現(xiàn)javax.servlet.http.HttpSessionListener接口,在Session被創(chuàng)建的時(shí)候通過調(diào)用ApplicationContextpublishEvent(ApplicationEvent event)發(fā)布HttpSessionCreatedEvent類型的事件,HttpSessionCreatedEvent類繼承自org.springframework.context.ApplicationEvent類的子類 HttpSessionApplicationEvent抽象類。

    concurrentSessionController使用sessionRegistry來完成對發(fā)布的Session的生命周期事件的處理,org.springframework.security.concurrent.SessionRegistryImpl(實(shí)現(xiàn)了SessionRegistry接口), SessionRegistryImpl類還實(shí)現(xiàn)了Spring Framework 的事件監(jiān)聽org.springframework.context.Application Listener接口,并實(shí)現(xiàn)了該接口定義的onApplicationEvent(ApplicationEvent event)方法用于處理Applic ationEvent類型的事件,如果你了解Spring Framework的事件處理,那么這里你應(yīng)該可以很好的理解。

    認(rèn)證管理器到此介紹完畢了,認(rèn)證過程過濾器也介紹完了,接下來我們繼續(xù)介紹過濾器鏈的下一個(gè)過濾器
    securityContextHolderAwareRequestFilter

    1 <bean id="securityContextHolderAwareRequestFilter"
    2     class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter"/>

    這個(gè)過濾器使用裝飾模式Decorate Model),裝飾的HttpServletRequest對象。其Wapper是ServletRequest包裝類HttpServletRequestWrapper的子類(如SavedRequestAwareWrapper或SecurityContextHolderAwareRequestWrapper),附上獲取用戶權(quán)限信息,request參數(shù),headers 和 cookies 的方法。

    rememberMeProcessingFilter過濾器配置:

    <bean id="rememberMeProcessingFilter"

        class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter"

        p:authenticationManager-ref="authenticationManager"

        p:rememberMeServices-ref="rememberMeServices"/>

    當(dāng)SecurityContextHolder中不存在Authentication用戶授權(quán)信息時(shí),rememberMeProcessingFilter就會(huì)調(diào)用rememberMeServices 的autoLogin()方法從cookie中獲取用戶信息自動(dòng)登錄。

    anonymousProcessingFilter過濾器配置:

    1 <bean id="anonymousProcessingFilter"
    2     class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter"
    3     p:key="springsecurity"
    4     p:userAttribute="anonymousUser,ROLE_ANONYMOUS"/>

    如果不存在任何授權(quán)信息時(shí),自動(dòng)添加匿名用戶身份至SecurityContextHolder中,就是這里配置的userAttribute,系統(tǒng)為用戶分配一個(gè)ROLE_ANONYMOUS權(quán)限。

    exceptionTranslationFilter(異常處理過濾器),該過濾器用來處理在系統(tǒng)認(rèn)證授權(quán)過程中拋出的異常,主要是處理AccessDeniedExceptionAuthenticationException兩個(gè)異常并根據(jù)配置跳轉(zhuǎn)到不同URL:

    1 <bean id="exceptionTranslationFilter"
    2     class="org.springframework.security.ui.ExceptionTranslationFilter"
    3     p:accessDeniedHandler-ref="accessDeniedHandler"
    4      p:authenticationEntryPoint-ref
    ="authenticationEntryPoint"/>
    5   <!-- 處理AccessDeniedException -->
    6 <bean id="accessDeniedHandler"
    7     class
    ="org.springframework.security.ui.AccessDeniedHandlerImpl"
    8     p:errorPage="/accessDenied.jsp"/>
    9 <bean id="authenticationEntryPoint"
    10      class
    ="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"
    11     p:loginFormUrl="/login.jsp"
    12     p:forceHttps="false"/>

    accessDeniedHandler用于處理AccessDeniedException異常,當(dāng)用戶沒有權(quán)限訪問當(dāng)前請求的資源時(shí)拋出此異常,并跳轉(zhuǎn)自這里配置的/accessDenied.jsp頁面。

    authenticationEntryPoint(認(rèn)證入口點(diǎn)),這里定義了用戶登錄的頁面。系統(tǒng)為我們提供了3個(gè)認(rèn)證入口點(diǎn)的實(shí)現(xiàn):

    認(rèn) 證 入 口 點(diǎn)

    作           用

    BasicProcessingFilterEntryPoint

    通過向?yàn)g覽器發(fā)送一個(gè)HTTP 401(未授權(quán))消息,由瀏覽器彈出登錄對話框,提示用戶登錄

    AuthenticationProcessingFilterEntryPoint

    將用戶重定向到一個(gè)基于HTML表單的登錄頁面

    CasProcessingFilterEntryPoint

    將用戶重定向至一個(gè)Yale CAS登錄頁面

    這里我們使用AuthenticationProcessingFilterEntryPoint認(rèn)證入口點(diǎn),提供給用戶一個(gè)友好的登錄界面,只是為了給用戶更好的體驗(yàn)。

    filterSecurityInterceptor(過濾器安全攔截器),該過濾器首先調(diào)用認(rèn)證管理器來判斷用戶是否已被成功驗(yàn)證,如果沒有被驗(yàn)證則重定向到登錄界面。否則,從Authentication獲取用戶的權(quán)限信息,然后從objectDefinitionSource中獲取URL所對應(yīng)的權(quán)限,最后調(diào)用accessDecisionManager(訪問決策管理器)來判斷用戶當(dāng)前擁有的權(quán)限是否與當(dāng)前受保護(hù)的URL資源對應(yīng)的權(quán)限匹配,如果匹配就可以訪問該URL資源,否則將拋出AccessDeniedException異常返回客戶端瀏覽器一個(gè)403錯(cuò)誤(如果用戶定義了accessDenied頁面則會(huì)被重定向到該頁,見:異常處理過濾器exceptionTranslationFilter中配置的accessDeniedHandler Bean),訪問決策管理的的工作機(jī)制將在隨后更詳細(xì)介紹,這里先給出過濾器安全攔截器的配置如下:

     1 <bean id="filterSecurityInterceptor"
     2 
     3     class="org.springframework.security.intercept.web.FilterSecurityInterceptor"
     4 
     5     p:authenticationManager-ref="authenticationManager"
     6 
     7     p:accessDecisionManager-ref="accessDecisionManager">
     8      <property name="objectDefinitionSource">
     9         <value><![CDATA[
    10 
    11      CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    12            PATTERN_TYPE_APACHE_ANT
    13            /admins/**=ROLE_SUPERVISOR      
    14              /user/**=ROLE_USER,IS_AUTHENTICATED_REMEMBERED       
    15              /default.jsp=ROLE_USER,IS_AUTHENTICATED_REMEMBERED
    16            /**=IS_AUTHENTICATED_ANONYMOUSLY
    17        ]]></value>
    18      </property>
    19 </bean>

    從配置可以看出來,過濾器安全攔截器用到了我們前面配置的認(rèn)證管理器,過濾器安全攔截器使用authenticationManager并調(diào)用它的providers(提供者列表)來對用戶的身份進(jìn)行驗(yàn)證并獲取用戶擁有的權(quán)限。如果用戶被成功認(rèn)證,過濾器安全攔截器將會(huì)使用accessDecisionManager(訪問決策管理器)來判斷已認(rèn)證的用戶是否有權(quán)限訪問受保護(hù)的資源,這些受保護(hù)的資源由objectDefinitionSource屬性定義。

    訪問決策管理器(accessDecisionManager)

     1 <bean id="accessDecisionManager"
     2     class="org.springframework.security.vote.AffirmativeBased"
     3      p:allowIfAllAbstainDecisions="false">
     4      <property name="decisionVoters">
     5         <list>
     6            <bean class="org.springframework.security.vote.RoleVoter"/>
     7            <bean class="org.springframework.security.vote.AuthenticatedVoter"/>
     8         </list>
     9      </property>
    10 </bean>

    身份驗(yàn)證只是Spring Security安全機(jī)制的第一步,訪問決策管理器驗(yàn)證用戶是否有權(quán)限訪問相應(yīng)的資源(filterSecurityInterceptor中objectDefinitionSource屬性定義的訪問URL需要的屬性信息)。

    org.springframework.security.AccessDecisionManager接口定義了用于驗(yàn)證用戶是否有權(quán)限訪問受保護(hù)資源的decide方法,另一個(gè)supports方法根據(jù)受保護(hù)資源的配置屬性(即訪問這些資源所需的權(quán)限)來判斷該訪問決策管理器是否能做出針對該資源的訪問決策。decide方法最終決定用戶有無訪問權(quán)限,如果沒有則拋出AccessDeniedException異常(面前也提到過,你應(yīng)該在回過頭去看看)。

    與認(rèn)證管理器類似,訪問決策管理器也不是由自己來實(shí)現(xiàn)訪問控制的,而是通過一組投票者來投票決定(通過調(diào)用投票者vote方法),訪問決策管理器統(tǒng)計(jì)投票結(jié)果并最終完成決策工作。下表列出了系統(tǒng)提供的3個(gè)訪問決策管理器的實(shí)現(xiàn):

    訪問決策管理器

    如 何 決 策

    AffirmativeBased

    當(dāng)至少有一個(gè)投票者投允許訪問時(shí)許訪問

    ConsensusBased

    當(dāng)所有投票者都投允許訪問時(shí)許訪問

    UnanimousBased

    當(dāng)沒有投票者投拒絕訪問時(shí)許訪問

    decisionVoters屬性為訪問決策管理器定義了一組進(jìn)行投票工作的投票者,那么這些投票者是如何進(jìn)行投票的呢?這就需要提org.springframework.security.vote.AccessDecisionVoter接口,所有的投票者都實(shí)現(xiàn)了這個(gè)接口并實(shí)現(xiàn)了其中的vote方法。該接口中還定義了3個(gè)int類型的常量:

    int ACCESS_GRANTED = 1;投贊成票

    int ACCESS_ABSTAIN = 0;投棄權(quán)票

    int ACCESS_DENIED = -1; 投反對票

    每個(gè)決策投票者都返回這3個(gè)常量中一個(gè),這取決與用戶是否有權(quán)限訪問當(dāng)前請求的資源,訪問決策管理器再對這些投票結(jié)果進(jìn)行統(tǒng)計(jì)。認(rèn)證投票者的配置如上面所示。

    loggerListener是一個(gè)可選項(xiàng),它和我們前面配置的Bean或者過濾器沒有關(guān)系,只是監(jiān)聽系統(tǒng)的一些事件(
    實(shí)現(xiàn)了ApplicationListener監(jiān)聽接口),被它監(jiān)聽的事件包括AuthenticationCredentialsNotFoundEvent事 件,AuthorizationFailureEvent事件,AuthorizedEvent事件,PublicInvocationEvent事件,相信你從他們 的名字就能看出來是一些什么樣的事件,除非你的e文比我還差勁。loggerListener配置如下:

    1 <bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>

    到此,本例所涉及到的所有配置都介紹完了,在下一篇中會(huì)介紹方法安全攔截器,以及如何使用它來保護(hù)我們的方法調(diào)用,以及前面提到過的會(huì)在下一篇中介紹的,這里不在一一列出。

    接下來就是JSP頁面了,首先是login.jsp:

     1 <c:if test="${not empty param.login_error}">
     2     登錄失敗,請重試。錯(cuò)誤原因:<br/>
     3     <font color="red">
     4         <c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION}">
     5             <c:out value="${SPRING_SECURITY_LAST_EXCEPTION}"></c:out>
     6         </c:if>
     7     </font>
     8 </c:if>
     9 <form action="<c:url value="/j_spring_security_check"/>" method="post">
    10     <table>
    11         <tr>
    12             <td><label for="username">username:</label></td>
    13             <td><input type="text" id="username" name="j_username"
                        value
    ="<c:out value="${SPRING_SECURITY_LAST_USERNAME}"/>"/></td>

    14         </tr>
    15         <tr>
    16             <td><label for="password">password:</label></td>
    17             <td><input type="password" id="password" name="j_password" value=""/></td>
    18         </tr>
    19         <tr><td></td>
    20             <td><input type="checkbox" name="_spring_security_remember_me">兩周內(nèi)記住我</td>
    21         </tr>
    22         <tr><td colspan="2"><input type="submit" value="提交"/>
    23         <input type="reset" value="重置"/></td></tr>
    24     </table>
    25 </form>

    如果你有看源代碼,上面的某些參數(shù),以及本文所有提及的東西你都不應(yīng)該感到陌生。其它頁面也不在列出了,還有就是如何讓它運(yùn)行起來,這些我相信你都能自己搞定。

    附件1:springsecurity.rar(不包括JAR包)

    補(bǔ)上使用命名空間配置實(shí)現(xiàn)的代碼,命名空間的詳細(xì)資料請參考Spring Security中文參考文檔,翻譯得很好,這里就不在累述了,配置文件中也有比較詳細(xì)的注釋。另外例子中還包括了自定義UserDetailService的實(shí)現(xiàn)已經(jīng)如何Ehcache緩存用戶信息,詳細(xì)的信息將在下一篇中講述。

    附件2:springsecurity-namespace.rar(包括部分JAR包)


    評論

    # re: 【總結(jié)】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 12:29 by fffffff
    寫的不錯(cuò)

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 12:48 by xiaocui
    o(∩_∩)o...好厲害?。。。。。。。。。。?/div>

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 14:30 by supermomo
    不錯(cuò),收藏

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 14:58 by Meatball
    我最近也在讀acegi的源代碼, 請教博主一個(gè)問題
    下面的filterInvocationDefinitionSource屬性注入, filterInvocationDefinitionSource在FilterChainProxy里面是一個(gè)FilterInvocationDefinitionSource對象, 但spring注入的是CDATA對象, 那是在什么地方將這個(gè)CDATA對象轉(zhuǎn)換成FilterInvocationDefinitionSource對象的呢?

    <bean id="filterChainProxy"
    class="org.springframework.security.util.FilterChainProxy">
    2 <property name="filterInvocationDefinitionSource">
    3 <value><![CDATA[
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    4 PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,logoutFilter,
    5 authenticationProcessingFilter,securityContextHolderAwareRequestFilter,
    6 rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,
    7 filterSecurityInterceptor
    8 ]]></value>
    9 </property>
    10 </bean>

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 15:20 by Hibernating
    如果文本包含了很多的"<"字符和"&"字符——就象程序代碼一樣,那么最好把他們都放到CDATA部件中。這樣CDATA部件之間的文本都會(huì)被解析器忽略。你可以試試把他們?nèi)チ艘部梢哉9ぷ鳌?/div>

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 20:11 by 尋道者
    很詳細(xì)啊,做個(gè)記號有時(shí)間慢慢看。

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-20 22:57 by xyz20003
    似乎沒有用到spring security新提供的namespace配置方式。
    我們正在翻譯spring securiy官方文檔,有興趣的話,請?zhí)嵋稽c(diǎn)兒建議,預(yù)覽地址在http://www.family168.com/tutorial/springsecurity/html/springsecurity.html

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-21 10:10 by regale
    不錯(cuò),收藏

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-21 10:21 by rubyol
    請問博主如何看待新版增加的namespace配置方式?

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一[未登錄]  回復(fù)  更多評論   

    2008-08-21 10:27 by Hibernating
    哈哈~~~我個(gè)人認(rèn)為,這種老的配置方法雖然復(fù)雜,但是更容易讓人理解。就像JSF和Struts,一個(gè)能明顯的感覺到請求響應(yīng)模式的存在,而另一個(gè)卻沒有,namespace配置方式就像JSF一樣,有些東西我們似乎看不見了。對于初學(xué)者我覺得還是應(yīng)該先用這種形式來配置,以加深對整個(gè)工作流程的理解。

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-21 10:31 by rubyol
    回復(fù)真快啊!

    # re: 【總結(jié)-含源代碼】Spring Security學(xué)習(xí)總結(jié)一  回復(fù)  更多評論   

    2008-08-22 19:51 by BeanSoft
    樓主圖畫的不錯(cuò)啊, 文章寫的更好, 什么軟件畫的? Visio?

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2008-08-29 20:24 by 藍(lán)劍
    樓主你好
    看到你在我那里的留言了,能詳細(xì)說說如何避免js/css/image等資源被
    acegi處理嗎?你說的定義成#NONE#不知道是什么意思。

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2008-09-01 09:02 by Hibernating
    謝謝你的關(guān)注,1.x版本中你可以查看org.acegisecurity.util.FilterChainProxy類,其中定義了一個(gè)變量public static final String TOKEN_NONE = "#NONE#",并在obtainAllDefinedFilters方法中有如下判斷
    if (!filterName.equals(TOKEN_NONE)) {
    list.add(this.applicationContext.getBean(filterName, Filter.class));
    };
    也就是說如果我們配置的過濾器名為#NONE#(例如:/js/**=#NONE#,/css/**==#NONE#,/image/**=#NONE#),那么就不會(huì)從Spring上下文中加載相應(yīng)的過濾器,那你在請求這些資源的時(shí)候當(dāng)然就不會(huì)過濾了,
    在2.0中也就定義這個(gè)變量,但是是在org.springframework.security.intercept.web.FIDSToFilterChainMapConverter類中有相應(yīng)的判斷語句,你可以看看源代碼。

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2008-09-01 14:04 by 路人
    請問樓主,你blog中抓圖內(nèi)的提示標(biāo)注圖形是用什么畫的?

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2008-09-01 15:16 by Hibernating
    word2007就可以畫啊。。。。

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2008-10-10 15:23 by cc
    非常感謝博主的辛勤勞動(dòng)

    有個(gè)無問題,為什么把應(yīng)用部署上去后,登錄老是說認(rèn)證失???而且登錄頁面沒有顯示失敗信息?

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2008-10-14 14:04 by java
    非常好。感謝樓主。不像好多人完全寫一堆垃圾敷衍了事。
    希望樓主能夠?qū)懜嗟暮脰|東

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2008-11-18 18:06 by 11
    博主能寫一個(gè)使用dao處理的說明就好了

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2008-12-16 10:32 by weilesi
    提交j_spring_security_check登錄后,Form中其他一些input參數(shù) 怎么得到?非常感謝

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2009-02-10 10:43 by jack
    請問樓主,SPRING SECURITY能和STRUTS整合嗎?

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2009-04-10 18:08 by algogz
    謝謝,這兩天學(xué)習(xí)一下,開始有點(diǎn)明白了。

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)[未登錄]  回復(fù)  更多評論   

    2009-06-27 10:19 by free
    org.springframework.security.util.FilterToBeanProxy這句,貌似直接使用org.springframework.web.filter.DelegatingFilterProxy這個(gè)就可以了吧,不用樓主那樣的吧

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2009-10-04 11:59 by 晉哥哥
    感謝樓主,最近在學(xué)習(xí)這個(gè)東東,文章看了,附件無法下載了,能否mail我一份?shoru#at#163.com

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2010-08-06 08:42 by kdmhh
    樓主辛苦了。請教樓主一個(gè)問題。Spring security默認(rèn)的登錄表單驗(yàn)證時(shí)j_spring_security_check。那我自己能不能寫表單的驗(yàn)證action?怎么實(shí)現(xiàn)啊?謝謝樓主幫忙解答一下。

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2013-03-15 11:02 by BL
    樓主寫的好!必須要感謝!

    # re: 【總結(jié)-含源碼】Spring Security學(xué)習(xí)總結(jié)一(補(bǔ)命名空間配置)  回復(fù)  更多評論   

    2013-12-07 12:14 by 都是浮云
    Spring的這一套機(jī)制的配置文件比小說都長,可見這些人有多無聊。
    主站蜘蛛池模板: 成年男女男精品免费视频网站 | 四虎亚洲精品高清在线观看| 欧洲人成在线免费| 亚洲精品麻豆av| 一级毛片大全免费播放下载| 亚洲国产中文字幕在线观看| 男女作爱免费网站| 亚洲美女高清一区二区三区 | 亚洲 暴爽 AV人人爽日日碰| 国产大片线上免费观看| 久久精品国产99国产精品亚洲 | 亚洲色婷婷六月亚洲婷婷6月| 黄 色一级 成 人网站免费| 亚洲精品亚洲人成在线观看| 免费国产污网站在线观看| 国产成人无码综合亚洲日韩 | 欧洲亚洲国产精华液| 国产免费人成视频在线观看 | 国精产品一区一区三区免费视频| 亚洲人成在线播放网站| 中文字幕无码免费久久| 亚洲小视频在线观看| 国产A∨免费精品视频| 亚洲性猛交XXXX| 99爱免费观看视频在线| 亚洲精品国产手机| 免费无码精品黄AV电影| 日韩欧美亚洲中文乱码| 亚洲一区二区三区免费| a毛片免费全部播放完整成| 亚洲毛片在线观看| 久久国内免费视频| 亚洲欧美精品午睡沙发| 亚洲AV日韩精品一区二区三区| 一级做a毛片免费视频| 亚洲AV无码精品无码麻豆| 免费h片在线观看网址最新| 亚洲色偷偷综合亚洲AV伊人蜜桃| 亚洲av午夜精品一区二区三区| 成人无码区免费A∨直播| 久久久久亚洲AV无码永不|