Spring Security(三十七):Part IV. Web Application Security
Most Spring Security users will be using the framework in applications which make user of HTTP and the Servlet API. In this part, we’ll take a look at how Spring Security provides authentication and access-control features for the web layer of an application. We’ll look behind the facade of the namespace and see which classes and interfaces are actually assembled to provide web-layer security. In some situations it is necessary to use traditional bean configuration to provide full control over the configuration, so we’ll also see how to configure these classes directly without the namespace.
13. The Security Filter Chain
Spring Security’s web infrastructure is based entirely on standard servlet filters. It doesn’t use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so it has no strong links to any particular web technology. It deals in HttpServletRequest
HttpServletResponse
s and doesn’t care whether the requests come from a browser, a web service client, an HttpInvoker
or an AJAX application.
Spring Security的Web基礎結構完全基於標準的servlet過濾器。它不在內部使用servlet或任何其他基於servlet的框架(例如Spring MVC),因此它沒有與任何特定Web技術的強大連結。它處理HttpServletRequest和HttpServletResponse,並不關心請求是來自瀏覽器,Web服務客戶端,HttpInvoker還是AJAX應用程式。
Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed from the configuration depending on which services are required. The ordering of the filters is important as there are dependencies between them. If you have been using
13.1 DelegatingFilterProxy
When using servlet filters, you obviously need to declare them in your web.xml
, or they will be ignored by the servlet container. In Spring Security, the filter classes are also Spring beans defined in the application context and thus able to take advantage of Spring’s rich dependency-injection facilities and lifecycle interfaces. Spring’s DelegatingFilterProxy
provides the link between web.xml
and the application context.
DelegatingFilterProxy
, you will see something like this in the
web.xml
file:
使用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>
Notice that the filter is actually a DelegatingFilterProxy
, and not the class that will actually implement the logic of the filter. What DelegatingFilterProxy
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 web application context lifecycle support and configuration flexibility. The bean must implement javax.servlet.Filter
and it must have the same name as that in the filter-name
element. Read the Javadoc for DelegatingFilterProxy
for more information
13.2 FilterChainProxy
Spring Security’s web infrastructure should only be used by delegating to an instance of FilterChainProxy
. The security filters should not be used by themselves. In theory you could declare each Spring Security filter bean that you require in your application context file and add a corresponding DelegatingFilterProxy
entry to web.xml
for each filter, making sure that they are ordered correctly, but this would be cumbersome and would clutter up the web.xml
file quickly if you have a lot of filters. FilterChainProxy
lets us add a single entry to web.xml
and deal entirely with the application context file for managing our web security beans. It is wired using a DelegatingFilterProxy
, just like in the example above, but with the filter-name
set to the bean name "filterChainProxy". The filter chain is then declared in the application context with the same bean name. Here’s an example:
<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>
The namespace element filter-chain
is used for convenience to set up the security filter chain(s) which are required within the application. [6]. It maps a particular URL pattern to a list of filters built up from the bean names specified in the filters
element, and combines them in a bean of type SecurityFilterChain
. The pattern
attribute takes an Ant Paths and the most specific URIs should appear first [7]. At runtime the FilterChainProxy
will locate the first URI pattern that matches the current web request and the list of filter beans specified by the filters
attribute will be applied to that request. The filters will be invoked in the order they are defined, so you have complete control over the filter chain which is applied to a particular URL.
SecurityContextPersistenceFilter
s in the filter chain (
ASC
is short for
allowSessionCreation
, a property of
SecurityContextPersistenceFilter
). As web services will never present a
jsessionid
on future requests, creating
HttpSession
s for such user agents would be wasteful. If you had a high-volume application which required maximum scalability, we recommend you use the approach shown above. For smaller applications, using a single
SecurityContextPersistenceFilter
(with its default
allowSessionCreation
as
true
) would likely be sufficient.
您可能已經注意到我們在過濾器鏈中聲明瞭兩個SecurityContextPersistenceFilter(ASC是allowSessionCreation的縮寫,是SecurityContextPersistenceFilter的一個屬性)。由於Web服務永遠不會出現未來請求的jsessionid,因此為這樣的使用者代理建立HttpSession將是浪費。如果您的大批量應用程式需要最大的可擴充套件性,我們建議您使用上面顯示的方法。對於較小的應用程式,使用單個SecurityContextPersistenceFilter(預設的allowSessionCreation為true)可能就足夠了。
Note that
FilterChainProxy
does not invoke standard filter lifecycle methods on the filters it is configured with. We recommend you use Spring’s application context lifecycle interfaces as an alternative, just as you would for any other Spring bean.
請注意,FilterChainProxy不會在配置的過濾器上呼叫標準過濾器生命週期方法。我們建議您使用Spring的應用程式上下文生命週期介面作為替代方法,就像使用任何其他Spring bean一樣。
When we looked at how to set up web security using
namespace configuration, we used a
DelegatingFilterProxy
with the name "springSecurityFilterChain". You should now be able to see that this is the name of the
FilterChainProxy
which is created by the namespace.
當我們檢視如何使用名稱空間配置設定Web安全性時,我們使用了名為“springSecurityFilterChain”的DelegatingFilterProxy。您現在應該能夠看到這是由名稱空間建立的FilterChainProxy的名稱。
13.2.1 Bypassing the Filter Chain
You can use the attribute filters = "none"
as an alternative to supplying a filter bean list. This will omit the request pattern from the security filter chain entirely. Note that anything matching this path will then have no authentication or authorization services applied and will be freely accessible. If you want to make use of the contents of the SecurityContext
contents during a request, then it must have passed through the security filter chain. Otherwise the SecurityContextHolder
will not have been populated and the contents will be null.
13.3 Filter Ordering
The order that filters are defined in the chain is very important. Irrespective of which filters you are actually using, the order should be as follows:
過濾器在鏈中定義的順序非常重要。無論您實際使用哪種過濾器,訂單應如下:ChannelProcessingFilter
, because it might need to redirect to a different protocol- ChannelProcessingFilter,因為它可能需要重定向到不同的協議
SecurityContextPersistenceFilter
, so aSecurityContext
can be set up in theSecurityContextHolder
at the beginning of a web request, and any changes to theSecurityContext
can be copied to theHttpSession
when the web request ends (ready for use with the next web request)- SecurityContextPersistenceFilter,因此可以在Web請求開始時在SecurityContextHolder中設定SecurityContext,並且當Web請求結束時(可以使用下一個Web請求準備好),可以將對SecurityContext的任何更改複製到HttpSession。
ConcurrentSessionFilter
, because it uses theSecurityContextHolder
functionality and needs to update theSessionRegistry
to reflect ongoing requests from the principal- ConcurrentSessionFilter,因為它使用SecurityContextHolder功能並需要更新SessionRegistry以反映來自主體的持續請求
- Authentication processing mechanisms -
UsernamePasswordAuthenticationFilter
,CasAuthenticationFilter
,BasicAuthenticationFilter
etc - so that theSecurityContextHolder
can be modified to contain a validAuthentication
request token - 身份驗證處理機制 - UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等 - 以便可以修改SecurityContextHolder以包含有效的身份驗證請求令牌
- The
SecurityContextHolderAwareRequestFilter
, if you are using it to install a Spring Security awareHttpServletRequestWrapper
into your servlet container - SecurityContextHolderAwareRequestFilter,如果您使用它將Spring安全感知HttpServletRequestWrapper安裝到您的servlet容器中
- The
JaasApiIntegrationFilter
, if aJaasAuthenticationToken
is in theSecurityContextHolder
this will process theFilterChain
as theSubject
in theJaasAuthenticationToken
- JaasApiIntegrationFilter,如果JaasAuthenticationToken位於SecurityContextHolder中,則會將FilterChain作為JaasAuthenticationToken中的Subject進行處理
RememberMeAuthenticationFilter
, so that if no earlier authentication processing mechanism updated theSecurityContextHolder
, and the request presents a cookie that enables remember-me services to take place, a suitable rememberedAuthentication
object will be put there- RememberMeAuthenticationFilter,這樣如果沒有更早的身份驗證處理機制更新SecurityContextHolder,並且請求提供了一個啟用記住我服務的cookie,那麼一個合適的記憶身份驗證物件將放在那裡
AnonymousAuthenticationFilter
, so that if no earlier authentication processing mechanism updated theSecurityContextHolder
, an anonymousAuthentication
object will be put there- AnonymousAuthenticationFilter,這樣如果沒有更早的身份驗證處理機制更新SecurityContextHolder,那麼匿名身份驗證物件將被放在那裡
ExceptionTranslationFilter
, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriateAuthenticationEntryPoint
can be launched- ExceptionTranslationFilter,用於捕獲任何Spring Security異常,以便可以返回HTTP錯誤響應或啟動相應的AuthenticationEntryPoint
FilterSecurityInterceptor
, to protect web URIs and raise exceptions when access is denied- FilterSecurityInterceptor,用於保護Web URI並在訪問被拒絕時引發異常