spring DelegatingFilterProxy管理過濾器


安全過濾器鏈 
Spring Security的web架構是完全基於標准的servlet過濾器的。它沒有在內部使用servlet或任何其他基於servlet的框架(比如spring mvc),所以它沒有與任何特定的web技術強行關聯。 它只管處理HttpServletRequest和HttpServletResponse,不關心請求時來自瀏覽器,web服務客戶端,HttpInvoker還是一個AJAX應用。 

Spring Security維護了一個過濾器鏈,每個過濾器擁有特定的功能,過濾器需要服務也會對應添加和刪除。過濾器的次序是非常重要的,它們之間都有依賴關系。 如果你已經使用了命名空間配置,過濾器會自動幫你配置, 你不需要定義任何SpringBean,但是有時候你需要完全控制Spring過濾器鏈,因為你使用了命名空間沒有提供的特性,或者你需要使用你自己自定義的類。 

1. DelegatingFilterProxy 
當使用servlet過濾器時,你很需要在你的web.xml中聲明它們, 它們可能被servlet容器忽略。在SpringSecurity,過濾器類也是定義在xml中的spring bean, 因此可以獲得Spring的依賴注入機制和生命周期接口。spring的DelegatingFilterProxy提供了在 web.xml和applicationcontext之間的聯系。 

當使用DelegatingFilterProxy,你會看到像web.xml文件中的這樣內容: 

myFilter org.springframework.web.filter.DelegatingFilterProxy myFilter /*  
注意這個過濾器其實是一個DelegatingFilterProxy,這個過濾器里沒有實現過濾器的任何邏輯。DelegatingFilterProxy做的事情是代理Filter的方法,從application context里獲得bean。這讓bean可以獲得spring web application context的生命周期支持,使配置較為輕便。bean必須實現javax.servlet.Filter接口,它必須和filter-name里定義的名稱是一樣的。查看DelegatingFilterProxy的javadoc獲得更多信息。 

2. FilterChainProxy 
現在應該清楚了,你可以聲明每個Spring Security過濾器bean,你在application context中需要的。把一個DelegatingFilterProxy入口添加到web.xml, 確認它們的次序是正確的。這是一種繁瑣的方式,會讓web.xml顯得十分雜亂,如果我們配置了太多過濾器的話。我們最好添加一個單獨的入口,在web.xml中,然后在application context中處理實體,管理我們的web安全bean。 這就是FilterChainProxy所做的事情。它使用DelegatingFilterProxy(就像上面例子中那樣),但是對應的class是org.springframework.security.web.FilterChainProxy。過濾器鏈是在application context中聲明的。這里有一個例子: 

<sec:filter-chain-mappath-type="ant"><sec:filter-chainpattern=" ebservices="" *"="" filters="securityContextPersistenceFilterWithASCFalse,basicAuthenticationFilter, exceptionTranslationFilter,filterSecurityInterceptor"> 
你可能注意到FilterSecurityInterceptor聲明的不同方式。命名空間元素filter-chain-map被用來設置安全過濾器鏈。它映射一個特定的URL模式,到過濾器鏈中,從bean名稱來定義的filters元素。它同時支持正則表達式和ant路徑,並且只使用第一個出現的匹配URI。在運行階段FilterChainProxy會定位當前web請求匹配的第一個URI模式,由filters屬性指定的過濾器bean列表將開始處理請求。過濾器會按照定義的順序依次執行,所以你可以對處理特定URL的過濾器鏈進行完全的控制。 

你可能注意到了,我們在過濾器鏈里聲明了兩個SecurityContextPersistenceFilter(ASC是allowSessionCreation的簡寫,是SecurityContextPersistenceFilter的一個屬性)。因為web服務從來不會在請求里帶上jsessionid,為每個用戶代理都創建一個HttpSession完全是一種浪費。如果你需要構建一個高等級最高可擴展性的系統,我們推薦你使用上面的配置方法。對於小一點兒的項目,使用一個HttpSessionContextIntegrationFilter(讓它的allowSessionCreation默認為true)就足夠了。 

在有關聲明周期的問題上,如果這些方法被FilterChainProxy自己調用,FilterChainProxy會始終根據下一層的Filter代理init(FilterConfig)和destroy()方法。這時,FilterChainProxy會保證初始化和銷毀操作只會在Filter上調用一次,而不管它在過濾器鏈中被聲明了多少次)。你控制着所有的抉擇,比如這些方法是否被調用或targetFilterLifecycle初始化參數DelegatingFilterProxy。默認情況下,這個參數是false,servlet容器生命周期調用不會傳播到DelegatingFilterProxy。 

當我們了解如何使用命名控制配置構建web安全。我們使用一個DelegatingFilterProxy,它的名字是“springSecurityFilterChain”。你應該現在可以看到FilterChainProxy的名字,它是由命名空間創建的。 

2.1. 繞過過濾器鏈 
通過命名空間,你可以使用filters = "none",來提供一個過濾器bean列表。這會朝向請求模式,使用安全過濾器鏈整體。注意任何匹配這個模式的路徑不會有任何授權或校驗的服務起作用,它們是可以自由訪問的。 

3. 過濾器順序 
定義在web.xml里的過濾器的順序是非常重要的。不論你實際使用的是哪個過濾器, 的順序應該像下面這樣:  

ChannelProcessingFilter,因為它可能需要重定向到其他協議。  

ConcurrentSessionFilter,因為它不使用SecurityContextHolder功能,但是需要更新SessionRegistry 來從主體中放映正在進行的請求。  

SecurityContextPersistenceFilter,這樣 SecurityContext可以在web請求的開始階段通過SecurityContextHolder建立,然后SecurityContext的任何修改都會在web請求結束的時候(為下一個web請求做准備)復制到HttpSession中。  

驗證執行機制 - UsernamePasswordAuthenticationFilter,CasAuthenticationFilter, BasicAuthenticationFilter 等等 - 這樣SecurityContextHolder 可以被修改,並包含一個合法的 Authentication請求標志。  

SecurityContextHolderAwareRequestFilter,如果,你使用它,把一個SpringSecurity提醒HttpServletRequestWrapper安裝到你的servlet容器里。  

RememberMeAuthenticationFilter,這樣如果之前的驗證執行機制沒有更新SecurityContextHolder,這個請求提供了一個可以使用的remember-me服務的cookie,一個對應的已保存的Authentication對象會被創建出來。  

AnonymousAuthenticationFilter,這樣如果之前的驗證執行機制沒有更新SecurityContextHolder,會創建一個匿名Authentication對象。  

ExceptionTranslationFilter,用來捕捉 SpringSecurity異常,這樣,可能返回一個HTTP錯誤響應,或者執行一個對應的AuthenticationEntryPoint。  

FilterSecurityInterceptor,保護web URI。  

4. 使用其他過濾器 —— 基於框架  
如果你在使用SiteMesh,確認Spring Security過濾器在SiteMesh過濾器之前調用。這可以保證SecurityContextHolder為每個SiteMesh渲染器及時創建。  



5. 其他配置例子  
方法一:  
web.xml配置一個  
  
DelegatingFilterProxy   
org.springframework.web.filter.DelegatingFilterProxy   
  
targetBeanName   
myFilter  //自己過濾器的名字  
  
  
targetFilterLifecycle   
true   
  
  

  
DelegatingFilterProxy   
/*   
  
方法二:  
web.xml配置一個  
  
myFilter   
org.springframework.web.filter.DelegatingFilterProxy   
  
targetFilterLifecycle   
true   
  
  

  
myFilter   
/*   
  

方法一或者二不同的地方就是在web.xml中的寫法不同而已沒有太大的區別,配完web.xml之后還要配置applicationContext.xml中的bean。  
applicationContext.xml配置:  
//指名具體的filter類  
<propertyname="service"> //需要注入的具體參數  
<refbean="service">  
  
  
//這里的service封裝了所有對數據庫的操作  
<propertyname="target">  
<beanclass="com.maimaiche.service.maimaicheserviceimpl">  
......  
  
  
  

--------------------------------------------------  
1、web.xml  
14379709.67309

Java代碼  收藏代碼
  1.  
  2.  
  3. appFilters  
  4. class >org.springframework.web.filter.DelegatingFilterProxy class
  5.  
  6. targetFilterLifecycle  
  7. true  
  8.  
  9.  
  10.  
  11. appFilters  
  12. /*  
  13.  



2、applicationContext-filter.xml  

Java代碼  "quality="high" allowscriptaccess="always"type="application/x-shockwave-flash"pluginspage="http://www.macromedia.com/go/getflashplayer">   收藏代碼
    1. "appFilters" class "org.springframework.security.util.FilterChainProxy" 
    2. "ant" 
    3. "characterEncodingFilter,commonParamsFilter"
    4. pattern="/**"/> 
    5.  
    6.  
    7. "characterEncodingFilter" class="org.springframework.web.filter.CharacterEncodingFilter"
    8. "encoding" value="UTF-8"/> 
    9. "forceEncoding" value="true"/> 
    10.  
    11. "commonParamsFilter" class="com.renren.wap.fuxi.filter.CommonParamsFilter"/>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM