1. 程式人生 > >Spring Security(三十七):Part IV. Web Application Security

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.

大多數Spring Security使用者將在使用HTTP和Servlet API的應用程式中使用該框架。在本部分中,我們將瞭解Spring Security如何為應用程式的Web層提供身份驗證和訪問控制功能。我們將檢視名稱空間的外觀,並檢視實際組裝的類和介面,以提供Web層安全性。在某些情況下,有必要使用傳統的bean配置來提供對配置的完全控制,因此我們還將看到如何在沒有名稱空間的情況下直接配置這些類。 

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

 s and 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 
namespace configuration
, then the filters are automatically configured for you and you don’t have to define any Spring beans explicitly but here may be times when you want full control over the security filter chain, either because you are using features which aren’t supported in the namespace, or you are using your own customized versions of classes. Spring Security在內部維護一個過濾器鏈,每個過濾器都有特定的責任,並根據所需的服務在配置中新增或刪除過濾器。過濾器的順序很重要,因為它們之間存在依賴關係。如果您一直在使用名稱空間配置,那麼將自動為您配置過濾器,您不必明確定義任何Spring bean,但這可能是您希望完全控制安全過濾器鏈的時候,因為您正在使用功能名稱空間中不支援,或者您使用自己的自定義版本的類。  

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.

使用servlet過濾器時,顯然需要在web.xml中宣告它們,否則servlet容器將忽略它們。在Spring Security中,過濾器類也是在應用程式上下文中定義的Spring bean,因此能夠利用Spring豐富的依賴注入工具和生命週期介面。 Spring的DelegatingFilterProxy提供了web.xml和應用程式上下文之間的連結。   When using  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

請注意,過濾器實際上是DelegatingFilterProxy,而不是實際實現過濾器邏輯的類。 DelegatingFilterProxy所做的是將Filter的方法委託給從Spring應用程式上下文中獲取的bean。這使bean能夠受益於Spring Web應用程式上下文生命週期支援和配置靈活性。 bean必須實現javax.servlet.Filter,它必須與filter-name元素中的名稱相同。有關更多資訊,請閱讀Javadoc for DelegatingFilterProxy

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:

Spring Security的Web基礎結構只能通過委託FilterChainProxy例項來使用。安全過濾器本身不應使用。從理論上講,您可以在應用程式上下文檔案中宣告所需的每個Spring Security過濾器bean,併為每個過濾器新增相應的DelegatingFilterProxy條目到web.xml,確保它們正確排序,但這會很麻煩並且會使如果您有很多過濾器,請快速使用web.xml檔案。 FilterChainProxy允許我們向web.xml新增一個條目,並完全處理應用程式上下文檔案以管理我們的Web安全bean。它使用DelegatingFilterProxy連線,就像上面的例子一樣,但是filter-name設定為bean名稱“filterChainProxy”。然後,在應用程式上下文中使用相同的bean名稱宣告過濾器鏈。這是一個例子:
<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.

名稱空間元素過濾器鏈用於方便設定應用程式中所需的安全過濾器鏈。 [6]。它將特定的URL模式對映到根據filters元素中指定的bean名稱構建的過濾器列表,並將它們組合在SecurityFilterChain型別的bean中。 pattern屬性採用Ant路徑,最具體的URI應首先出現[7]。在執行時,FilterChainProxy將找到與當前Web請求匹配的第一個URI模式,並且filters屬性指定的過濾器bean列表將應用於該請求。過濾器將按照定義的順序呼叫,因此您可以完全控制應用於特定URL的過濾器鏈。   You may have noticed we have declared two  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.

您可以使用屬性filters =“none”作為提供過濾器bean列表的替代方法。這將完全省略安全過濾器鏈中的請求模式。請注意,與此路徑匹配的任何內容都將不會應用任何身份驗證或授權服務,並且可以自由訪問。如果要在請求期間使用SecurityContext內容的內容,則它必須已通過安全篩選器鏈。否則,將不會填充SecurityContextHolder,並且內容將為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 a SecurityContext can be set up in the SecurityContextHolder at the beginning of a web request, and any changes to the SecurityContext can be copied to the HttpSession 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 the SecurityContextHolder functionality and needs to update the SessionRegistry to reflect ongoing requests from the principal
  • ConcurrentSessionFilter,因為它使用SecurityContextHolder功能並需要更新SessionRegistry以反映來自主體的持續請求
  • Authentication processing mechanisms - UsernamePasswordAuthenticationFilterCasAuthenticationFilterBasicAuthenticationFilter etc - so that the SecurityContextHolder can be modified to contain a valid Authentication request token
  • 身份驗證處理機制 - UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等 - 以便可以修改SecurityContextHolder以包含有效的身份驗證請求令牌
  • The SecurityContextHolderAwareRequestFilter, if you are using it to install a Spring Security aware HttpServletRequestWrapper into your servlet container
  • SecurityContextHolderAwareRequestFilter,如果您使用它將Spring安全感知HttpServletRequestWrapper安裝到您的servlet容器中
  • The JaasApiIntegrationFilter, if a JaasAuthenticationToken is in the SecurityContextHolder this will process the FilterChain as the Subject in the JaasAuthenticationToken
  • JaasApiIntegrationFilter,如果JaasAuthenticationToken位於SecurityContextHolder中,則會將FilterChain作為JaasAuthenticationToken中的Subject進行處理
  • RememberMeAuthenticationFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, and the request presents a cookie that enables remember-me services to take place, a suitable remembered Authentication object will be put there
  • RememberMeAuthenticationFilter,這樣如果沒有更早的身份驗證處理機制更新SecurityContextHolder,並且請求提供了一個啟用記住我服務的cookie,那麼一個合適的記憶身份驗證物件將放在那裡
  • AnonymousAuthenticationFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, an anonymous Authentication 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 appropriate AuthenticationEntryPoint can be launched
  • ExceptionTranslationFilter,用於捕獲任何Spring Security異常,以便可以返回HTTP錯誤響應或啟動相應的AuthenticationEntryPoint
  • FilterSecurityInterceptor, to protect web URIs and raise exceptions when access is denied
  • FilterSecurityInterceptor,用於保護Web URI並在訪問被拒絕時引發異常