Spring Security 04

轉至:Elim的博客http://elim.iteye.com/blog/2161648html

Filter Porxy

DelegatingFilterProxy

DelegationFilterProxy不是spring security的入口,它實際上是spring的一個代理類(org.springframework.web.filter.DelegatingFilterProxy),做用是將spring 與 spring security融合。
它內部代理的是spring scurity的FilterChainProxy(org.springframework.security.web.FilterChainProxy)代理類。真正執行工做的是是FilterChainProxy。FilterChainProxy中會加載
全部的spring security filter,而後調用每一個Filter的doFilter方法。targetFilterLifecycle初始化爲true時,會調用全部filer的init初始化方法
詳情查看https://www.cnblogs.com/hzhuxin/archive/2011/12/19/2293730.htmlweb

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 

  <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>  <!-- 默認是false -->
    </init-param>
 </filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>

 </filter-mapping>

FilterChainProxy

Spring security容許咱們在配置文件中配置多個http元素,以針對不一樣形式的URL使用不一樣的安全控制。Spring Security將會爲每個http元素建立對應的FilterChain,同時按照它們的聲明順序加入到FilterChainProxy。因此當咱們同時定義多個http元素時要確保將更具備特性的URL配置在前。spring

<security:http pattern="/login*.jsp*" security="none"/>

   <!-- http元素的pattern屬性指定當前的http對應的FilterChain將匹配哪些URL,如未指定將匹配全部的請求 -->

   <security:http pattern="/admin/**">

      <security:intercept-url pattern="/**" access="ROLE_ADMIN"/>

   </security:http>

   <security:http>

      <security:intercept-url pattern="/**" access="ROLE_USER"/>

   </security:http>

須要注意的是http擁有一個匹配URL的pattern,未指定時表示匹配全部的請求,其下的子元素intercept-url也有一個匹配URL的pattern,該pattern是在http元素對應pattern基礎上的,也就是說一個請求必須先知足http對應的pattern纔有可能知足其下intercept-url對應的pattern。api

Filter Chain中的Filer,按照前後順序

  • ChannelProcessingFilter,若是你訪問的channel錯了,那首先就會在channel之間進行跳轉,如http變爲https。安全

  • SecurityContextPersistenceFilter,這樣的話在一開始進行request的時候就能夠在SecurityContextHolder中創建一個SecurityContext,而後在請求結束的時候,任何對SecurityContext的改變均可以被copy到HttpSession。cookie

  • ConcurrentSessionFilter,由於它須要使用SecurityContextHolder的功能,並且更新對應session的最後更新時間,以及經過SessionRegistry獲取當前的SessionInformation以檢查當前的session是否已通過期,過時則會調用LogoutHandler。session

  • 認證處理機制,如UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等,以致於SecurityContextHolder能夠被更新爲包含一個有效的Authentication請求。app

  • SecurityContextHolderAwareRequestFilter,它將會把HttpServletRequest封裝成一個繼承自HttpServletRequestWrapper的SecurityContextHolderAwareRequestWrapper,同時使用SecurityContext實現了HttpServletRequest中與安全相關的方法。jsp

  • JaasApiIntegrationFilter,若是SecurityContextHolder中擁有的Authentication是一個JaasAuthenticationToken,那麼該Filter將使用包含在JaasAuthenticationToken中的Subject繼續執行FilterChain。ui

  • RememberMeAuthenticationFilter,若是以前的認證處理機制沒有更新SecurityContextHolder,而且用戶請求包含了一個Remember-Me對應的cookie,那麼一個對應的Authentication將會設給SecurityContextHolder。

  • AnonymousAuthenticationFilter,若是以前的認證機制都沒有更新SecurityContextHolder擁有的Authentication,那麼一個AnonymousAuthenticationToken將會設給SecurityContextHolder。

  • ExceptionTransactionFilter,用於處理在FilterChain範圍內拋出的AccessDeniedException和AuthenticationException,並把它們轉換爲對應的Http錯誤碼返回或者對應的頁面。

  • FilterSecurityInterceptor,保護Web URI,而且在訪問被拒絕時拋出異常。

自定義Filter,並添加到FilterChain

使用NameSpace時添加Filter到FilterChain是經過http元素下的custom-filter元素來定義的。定義custom-filter時須要咱們經過ref屬性指定其對應關聯的是哪一個Filter,此外還須要經過position、before或者after指定該Filter放置的位置。eg:position=」CAS_FILTER」就表示將定義的Filter放在CAS_FILTER對應的那個位置

Filter別名

別名 Filter類 對應元素或屬性
CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channe
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter http/session-management/concurrency-control
LOGOUT_FILTER LogoutFilter http/logout
X509_FILTER X509AuthenticationFilter http/x509
PRE_AUTH_FILTER AstractPreAuthenticatedProcessingFilter 的子類
CAS_FILTER CasAuthenticationFilter
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login
BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http@servlet-api-provision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http@jaas-api-provision
REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me
ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous
SESSION_MANAGEMENT_FILTER SessionManagementFilter http/session-managemen
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http
SWITCH_USER_FILTER SwitchUserFilter

Spring Security定義好的核心Filter

FilterSecurityInterceptor

FilterSecurityInterceptor是用於保護Http資源的,它須要一個AccessDecisionManager和一個AuthenticationManager的引用。它會從SecurityContextHolder獲取Authentication,而後經過SecurityMetadataSource能夠得知當前請求是否在請求受保護的資源。對於請求那些受保護的資源,若是Authentication.isAuthenticated()返回false或者FilterSecurityInterceptor的alwaysReauthenticate屬性爲true,那麼將會使用其引用的AuthenticationManager再認證一次,認證以後再使用認證後的Authentication替換SecurityContextHolder中擁有的那個。而後就是利用AccessDecisionManager進行權限的檢查。
咱們在使用基於NameSpace的配置時所配置的intercept-url就會跟FilterChain內部的FilterSecurityInterceptor綁定。若是要本身定義FilterSecurityInterceptor對應的bean,那麼該bean定義大體以下所示:

<bean id="filterSecurityInterceptor"

   class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">

      <property name="authenticationManager" ref="authenticationManager" />

      <property name="accessDecisionManager" ref="accessDecisionManager" />

      <property name="securityMetadataSource">

         <security:filter-security-metadata-source>

            <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />

            <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" />

         </security:filter-security-metadata-source>

      </property>

   </bean>

filter-security-metadata-source用於配置其securityMetadataSource屬性。intercept-url用於配置須要攔截的URL與對應的權限關係。

ExceptionTranslationFilter

經過前面的介紹咱們知道在Spring Security的Filter鏈表中ExceptionTranslationFilter就放在FilterSecurityInterceptor的前面。而ExceptionTranslationFilter是捕獲來自FilterChain的異常,並對這些異常作處理。ExceptionTranslationFilter可以捕獲來自FilterChain全部的異常,可是它只會處理兩類異常,AuthenticationException和AccessDeniedException,其它的異常它會繼續拋出。若是捕獲到的是AuthenticationException,那麼將會使用其對應的AuthenticationEntryPoint的commence()處理。若是捕獲的異常是一個AccessDeniedException,那麼將視當前訪問的用戶是否已經登陸認證作不一樣的處理,若是未登陸,則會使用關聯的AuthenticationEntryPoint的commence()方法進行處理,不然將使用關聯的AccessDeniedHandler的handle()方法進行處理。
AuthenticationEntryPoint是在用戶沒有登陸時用於引導用戶進行登陸認證的,在實際應用中應根據具體的認證機制選擇對應的AuthenticationEntryPoint。
AccessDeniedHandler用於在用戶已經登陸了,可是訪問了其自身沒有權限的資源時作出對應的處理。ExceptionTranslationFilter擁有的AccessDeniedHandler默認是AccessDeniedHandlerImpl,其會返回一個403錯誤碼到客戶端。咱們能夠經過顯示的配置AccessDeniedHandlerImpl,同時給其指定一個errorPage使其能夠返回對應的錯誤頁面。固然咱們也能夠實現本身的AccessDeniedHandler。

<bean id="exceptionTranslationFilter"
      class="org.springframework.security.web.access.ExceptionTranslationFilter">
      <property name="authenticationEntryPoint">
         <bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <property name="loginFormUrl" value="/login.jsp" />
         </bean>
      </property>
      <property name="accessDeniedHandler">
         <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
            <property name="errorPage" value="/access_denied.jsp" />
         </bean>
      </property>
   </bean>

在上述配置中咱們指定了AccessDeniedHandler爲AccessDeniedHandlerImpl,同時爲其指定了errorPage,這樣發生AccessDeniedException後將轉到對應的errorPage上。指定了AuthenticationEntryPoint爲使用表單登陸的LoginUrlAuthenticationEntryPoint。此外,須要注意的是若是該filter是做爲自定義filter加入到由NameSpace自動創建的FilterChain中時需把它放在內置的ExceptionTranslationFilter後面,不然異常都將被內置的ExceptionTranslationFilter所捕獲。

相關文章
相關標籤/搜索