##13.the security Filter chainjava
spring security的web機制是基於標準的servlet攔截器的.它沒有使用servlet或其餘基於servlet的框架,所以它同web技術沒有太強的關聯.他處理httpServletRequest和response時,不會關心這些請求是來自瀏覽器,仍是其餘web服務客戶端,一個HttpInvoker or ajax應用.web
spring安全保持一個互相關聯的攔截鏈.每一個攔截鏈都有特定的職責並根據服務的需求來決定他們是否被添加.他們之間排序也很重要.有時你須要自定義這些類的版本.ajax
##13.1 DelegatingFilterProxy正則表達式
當你使用servlet攔截器,你須要在你的web.xml裏聲明他們.不然就會被servlet容器忽略.spring
以下使用DelegatingFilterProxy,web.xml以下:瀏覽器
<filter> <filter-name>myFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這個攔截器是一個DelegatingFilterProxy,而不是實際上實現的攔截器.delegatingFilterProxy代理從spring應用上下文中獲取的bean的攔截器方法.安全
###13.2 FilterChainProxyrestful
spring security的web架構只應該用來代理FilterChainProxy的實例.理論上你能夠在web.xml裏註冊各類filters,但這樣會使是xml文件散亂.cookie
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> <constructor-arg> <list> <sec:filter-chain pattern="/restful/**" filters=" securityContextPersistenceFilterWithASCFalse, basicAuthenticationFilter, exceptionTranslationFilter, filterSecurityInterceptor" /> <sec:filter-chain pattern="/**" filters=" securityContextPersistenceFilterWithASCTrue, formLoginFilter, exceptionTranslationFilter, filterSecurityInterceptor" /> </list> </constructor-arg> </bean>
上例中根據url來區分. 你可使用屬性filters="none"來支持.這樣會排除filter以外.若是你想使用securityContextHolder,那必須通過攔截鏈.session
###13.3 攔截器順序 順序應該以下:
ChannelProcessingFilter,它可能會重定向到不一樣的協議.
SecurityContextPersistentceFilter,因此securityContextHolder安裝SecurityContext,任何的一個改變都會到httpSession裏.
ConcurrentSessionFilter 由於可使用SecurityContextHolder的功能,因此可使用SessionRegistry來反應來自主體的請求.
Authentication processing mechanisms 認證處理機制,UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等.因此springContextHolder會發生改變
SecurityContextHolderAwareRequestFilter.用來向你的servlet容器裏安裝HttpServletRequestWrapper組件
JaasApiIntegrationFilter,若是SecurityContextHolder裏有JaasAuthenticationToken,那麼就能夠經過攔截器
RememberMeAuthenticationFilter.若是沒有更早的安全認證機制來更新SecurityContextHolder,且請求中的表明的cookie能使remember-me發生做用,那麼一個適當的Authentication對象就會裝進去.
AnonymousAuthenticationFilter.若是以前的處理機制沒有更新SecurityContextHolder,就會設置一個匿名的Authentication對象.
ExceptionTranslationFilter,捕獲異常,能夠返回http錯誤響應,或合適AuthenticationEntryPoint.
FilterSecurityInterceptor,用來保護web URIs,當訪問受限會拋出異常
##13.4 Request Matching and httpFirewall
spring security有幾個區域來決定那個請求應該被處理.當FilterChainProxy決定那個請求能夠經過,FilterSecurityInterceptor決定那個安全限制適用於一個規則.
servlet規則定義了幾種能被getter方法訪問的httpServletRequest屬性,如contextPath,servletPath,pathInfo,queryString.contextPath能夠被忽略.但不幸的是,servletPath,pathInfo的值沒有被準肯定義.例如,每一個url的部分可能包含屬性值.可是該規則沒有說明是否要包含在servletPath和pathInfo值中,還有不一樣servlet容器的區別.若是一個容器沒有從url值中剝離這些參數很危險,攻擊者可能把它們添加到請求url中,引發模板匹配的成功或失敗.其餘的變種在url請求中也是可能的.例如,他應該包含路徑轉化序列(如/../)或混合路徑轉化序列(//),那麼這會引發正則表達式失敗.有些容器會在servlet匹配以前將他們正常化,而有些則不會.爲了保護這些問題,FilterChainProxy會使用HttpFirewall的策略來檢測組裝這些請求.不正常的請求默認會被拒絕.servletPath和pathInfo是由容器來解碼的,因此你的應用不該該有任何有效的路徑包含分號,若是有,則會被刪除.
默認使用ant風格路徑,這個是最好的選擇.這個策略是經過AntpathRequestMatcher類實現的,它大小寫敏感,匹配了servletPath和pathInfo,且忽略了queryString.
若是你須要更強力的匹配策略,那你可使用正則表達式.這個策略是RegexRequestMatcher實現的,查看javadoc以瞭解更多.
實際上咱們還在服務層使用訪問控制,不徹底依賴web層的安全防禦.url的變化很難統計這些應用支持的url的數量,已經這些請求該如何被操做.你應該經過簡單的例子來測試這些路徑.通常狀況下是默認拒絕的方式.
Security定義的安全很穩健,難以繞過.因此你應該更好的利用spring security的方法.
HttpFirewall經過拒絕新行字符來拒絕http響應.
###13.5 使用其餘基於攔截器的框架
要講spring security的攔截器放在其餘攔截器以前./
###13.6 高級命名空間配置
<!-- Stateless RESTful service using Basic authentication --> <http pattern="/restful/**" create-session="stateless"> <intercept-url pattern='/**' access="hasRole('REMOTE')" /> <http-basic /> </http> <!-- Empty filter chain for the login page --> <http pattern="/login.htm*" security="none"/> <!-- Additional filter chain for normal users, matching all other requests --> <http> <intercept-url pattern='/**' access="hasRole('USER')" /> <form-login login-page='/login.htm' default-target-url="/home.htm"/> <logout /> </http>