1. 程式人生 > >Spring Security(二十一):6.3 Advanced Web Features

Spring Security(二十一):6.3 Advanced Web Features

6.3.1 Remember-Me Authentication (記住我的身份驗證)

See the separate Remember-Me chapter for information on remember-me namespace configuration.

有關remember-me名稱空間配置的資訊,請參閱單獨的Remember-Me章節。

6.3.2 Adding HTTP/HTTPS Channel Security(新增HTTP / HTTPS通道安全性)

If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the requires-channel

 attribute on <intercept-url>:

如果您的應用程式同時支援HTTP和HTTPS,並且您要求只能通過HTTPS訪問特定URL,則可以使用<intercept-url>上的requires-channel屬性直接支援:
<http>
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
...
</http>

With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL [5]. The available options are "http", "https" or "any". Using the value "any" means that either HTTP or HTTPS can be used.

有了這種配置,如果使用者嘗試使用HTTP訪問與“/ secure / **”模式匹配的任何內容,它們將首先被重定向到HTTPS URL [5]。可用選項為“http”,“https”或“any”。使用值“any”表示可以使用HTTP或HTTPS。   If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows: 如果您的應用程式使用HTTP和/或HTTPS的非標準埠,則可以指定埠對映列表,如下所示:  
<http>
...
<port-mappings>
	<port-mapping http="9080" https="9443"/>
</port-mappings>
</http>

Note that in order to be truly secure, an application should not use HTTP at all or switch between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.

請注意,為了確保安全,應用程式根本不應使用HTTP或在HTTP和HTTPS之間切換。它應該以HTTPS(使用者輸入HTTPS URL)開始,並始終使用安全連線,以避免任何中間人攻擊的可能性。

6.3.3 Session Management

Detecting Timeouts(檢測超時)

You can configure Spring Security to detect the submission of an invalid session ID and redirect the user to an appropriate URL. This is achieved through the session-management element:

您可以將Spring Security配置為檢測提交的無效會話ID,並將使用者重定向到適當的URL。這是通過session-management元素實現的:  
<http>
...
<session-management invalid-session-url="/invalidSession.htm" />
</http>

Note that if you use this mechanism to detect session timeouts, it may falsely report an error if the user logs out and then logs back in without closing the browser. This is because the session cookie is not cleared when you invalidate the session and will be resubmitted even if the user has logged out. You may be able to explicitly delete the JSESSIONID cookie on logging out, for example by using the following syntax in the logout handler:

請注意,如果您使用此機制來檢測會話超時,則可能會錯誤地報告錯誤,如果使用者登出,然後在不關閉瀏覽器的情況下重新登入。這是因為當您使會話無效時,會話cookie不會被清除,即使使用者已登出,也會重新提交。您可以在登出時顯式刪除JSESSIONID cookie,例如在登出處理程式中使用以下語法:  
<http>
<logout delete-cookies="JSESSIONID" />
</http>

Unfortunately this can’t be guaranteed to work with every servlet container, so you will need to test it in your environment

不幸的是,這不能保證與每個servlet容器一起使用,因此您需要在您的環境中對其進行測試   If you are running your application behind a proxy, you may also be able to remove the session cookie by configuring the proxy server. For example, using Apache HTTPD’s mod_headers, the following directive would delete the  JSESSIONID cookie by expiring it in the response to a logout request (assuming the application is deployed under the path  /tutorial): 如果您在代理後面執行應用程式,則還可以通過配置代理伺服器來刪除會話cookie。例如,使用Apache HTTPD的mod_headers,以下指令將通過在對登出請求的響應中使其失效來刪除JSESSIONID cookie(假設應用程式部署在路徑/教程下):  
<LocationMatch "/tutorial/logout">
Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
</LocationMatch>

Concurrent Session Control

If you wish to place constraints on a single user’s ability to log in to your application, Spring Security supports this out of the box with the following simple additions. First you need to add the following listener to your web.xml file to keep Spring Security updated about session lifecycle events:

如果您希望對單個使用者登入應用程式的能力施加約束,Spring Security會通過以下簡單新增為開箱即用提供支援。首先,您需要將以下偵聽器新增到web.xml檔案中,以使Spring Security更新有關會話生命週期事件的資訊:   Then add the following lines to your application context: 然後將以下行新增到應用程式上下文中:  
<http>
...
<session-management>
	<concurrency-control max-sessions="1" />
</session-management>
</http>

This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated. Often you would prefer to prevent a second login, in which case you can use

這將阻止使用者多次登入 - 第二次登入將導致第一次失效。通常您更願意阻止第二次登入,在這種情況下您可以使用  
<http>
...
<session-management>
	<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>

The second login will then be rejected. By "rejected", we mean that the user will be sent to the authentication-failure-url if form-based login is being used. If the second authentication takes place through another non-interactive mechanism, such as "remember-me", an "unauthorized" (401) error will be sent to the client. If instead you want to use an error page, you can add the attribute session-authentication-error-url to the session-management element.

然後將拒絕第二次登入。 “被拒絕”是指如果使用基於表單的登入,使用者將被髮送到authentication-failure-url。如果第二次認證是通過另一種非互動機制發生的,例如“記住我”,則會向客戶端傳送“未授權”(401)錯誤。如果您想要使用錯誤頁面,則可以將屬性session-authentication-error-url新增到session-management元素。   If you are using a customized authentication filter for form-based login, then you have to configure concurrent session control support explicitly. More details can be found in the  Session Management chapter. 如果您使用自定義身份驗證篩選器進行基於表單的登入,則必須明確配置併發會話控制支援。更多詳細資訊可在“會話管理”一章中找到。

Session Fixation Attack Protection(會話固定攻擊保護)

Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example). Spring Security protects against this automatically by creating a new session or otherwise changing the session ID when a user logs in. If you don’t require this protection, or it conflicts with some other requirement, you can control the behavior using the session-fixation-protection attribute on <session-management>, which has four options

會話固定攻擊是潛在的風險,惡意攻擊者可能通過訪問站點來建立會話,然後說服其他使用者使用相同的會話登入(通過向他們傳送包含會話識別符號作為引數的連結,例)。 Spring Security會在使用者登入時通過建立新會話或以其他方式更改會話ID來自動防止此問題。如果您不需要此保護,或者它與某些其他要求衝突,您可以使用會話固定來控制行為<session-management>的-protection屬性,有四個選項  
  • none - Don’t do anything. The original session will be retained.
  • 什麼都不做原始會話將保留。  
  • newSession - Create a new "clean" session, without copying the existing session data (Spring Security-related attributes will still be copied).
  • 建立一個新的“乾淨”會話,而不復制現有的會話資料(仍將複製與Spring Security相關的屬性)。  
  • migrateSession - Create a new session and copy all existing session attributes to the new session. This is the default in Servlet 3.0 or older containers.
  • 建立新會話並將所有現有會話屬性複製到新會話。這是Servlet 3.0或舊容器中的預設設定。  
  • changeSessionId - Do not create a new session. Instead, use the session fixation protection provided by the Servlet container (HttpServletRequest#changeSessionId()). This option is only available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in older containers will result in an exception. This is the default in Servlet 3.1 and newer containers.
  • 不要建立新會話。而是使用Servlet容器提供的會話固定保護(HttpServletRequest#changeSessionId())。此選項僅適用於Servlet 3.1(Java EE 7)和更新的容器。在舊容器中指定它將導致異常。這是Servlet 3.1和更新容器中的預設設定。 

When session fixation protection occurs, it results in a SessionFixationProtectionEvent being published in the application context. If you use changeSessionId, this protection will also result in any javax.servlet.http.HttpSessionIdListener s being notified, so use caution if your code listens for both events. See the Session Management chapter for additional information.

發生會話固定保護時,會導致在應用程式上下文中釋出SessionFixationProtectionEvent。如果使用changeSessionId,此保護也將導致通知任何javax.servlet.http.HttpSessionIdListener,因此如果您的程式碼偵聽這兩個事件,請務必小心。有關其他資訊,請參閱會話管理章節。  

6.3.4 OpenID Support

The namespace supports OpenID login either instead of, or in addition to normal form-based login, with a simple change:

除了普通的基於表單的登入之外,名稱空間支援OpenID登入,只需進行簡單的更改:  
<http>
<intercept-url pattern="/**" access="ROLE_USER" />
<openid-login />
</http>

You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory <user-service>:

然後,您應該使用OpenID提供程式(例如myopenid.com)註冊自己,並將使用者資訊新增到記憶體<user-service>:
<user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />

You should be able to login using the myopenid.com site to authenticate. It is also possible to select a specific UserDetailsService bean for use OpenID by setting the user-service-ref attribute on the openid-login element. See the previous section on authentication providers for more information. Note that we have omitted the password attribute from the above user configuration, since this set of user data is only being used to load the authorities for the user. A random password will be generated internally, preventing you from accidentally using this user data as an authentication source elsewhere in your configuration.

您應該能夠使用myopenid.com網站進行身份驗證登入。通過在openid-login元素上設定user-service-ref屬性,還可以選擇特定的UserDetailsS​​ervice bean以使用OpenID。有關更多資訊,請參閱上一節有關身份驗證提供程請注意,我們已從上述使用者配置中省略了password屬性,因為此組使用者資料僅用於載入使用者的許可權。將在內部生成隨機密碼,以防止您意外地將此使用者資料用作配置中其他位置的身份驗證源。

Attribute Exchange(屬性交換)

Support for OpenID attribute exchange. As an example, the following configuration would attempt to retrieve the email and full name from the OpenID provider, for use by the application:

支援OpenID屬性交換。例如,以下配置將嘗試從OpenID提供程式檢索電子郵件和全名,以供應用程式使用:
<openid-login>
<attribute-exchange>
	<openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
	<openid-attribute name="name" type="http://axschema.org/namePerson"/>
</attribute-exchange>
</openid-login>

The "type" of each OpenID attribute is a URI, determined by a particular schema, in this case http://axschema.org/. If an attribute must be retrieved for successful authentication, the required attribute can be set. The exact schema and attributes supported will depend on your OpenID provider. The attribute values are returned as part of the authentication process and can be accessed afterwards using the following code:

每個OpenID屬性的“型別”是由特定模式確定的URI,在本例中為http://axschema.org/。如果必須檢索屬性以進行成功驗證,則可以設定所需的屬性。支援的確切架構和屬性取決於您的OpenID提供程式。屬性值作為身份驗證過程的一部分返回,之後可以使用以下程式碼進行訪問:  
OpenIDAuthenticationToken token =
	(OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
List<OpenIDAttribute> attributes = token.getAttributes();

The OpenIDAttribute contains the attribute type and the retrieved value (or values in the case of multi-valued attributes). We’ll see more about how the SecurityContextHolder class is used when we look at core Spring Security components in the technical overview chapter. Multiple attribute exchange configurations are also be supported, if you wish to use multiple identity providers. You can supply multiple attribute-exchange elements, using an identifier-matcher attribute on each. This contains a regular expression which will be matched against the OpenID identifier supplied by the user. See the OpenID sample application in the codebase for an example configuration, providing different attribute lists for the Google, Yahoo and MyOpenID providers.

OpenIDAttribute包含屬性型別和檢索的值(或多值屬性的值)。在我們檢視技術概述章節中的核心Spring Security元件時,我們將看到更多關於如何使用SecurityContextHolder類的資訊。如果您希望使用多個身份提供程式,也支援多個屬性交換配置。您可以使用每個元素的identifier-matcher屬性提供多個屬性交換元素。它包含一個正則表示式,該表示式將與使用者提供的OpenID識別符號進行匹配。請參閱程式碼庫中的OpenID示例應用程式以獲取示例配置,為Google,Yahoo和MyOpenID提供程式提供不同的屬性列表。

6.3.5 Response Headers

For additional information on how to customize the headers element refer to the Chapter 20, Security HTTP Response Headers section of the reference.

有關如何自定義headers元素的其他資訊,請參閱參考的第20章,Security HTTP Response Headers部分。  

6.3.6 Adding in Your Own Filters(新增自己的過濾器)

If you’ve used Spring Security before, you’ll know that the framework maintains a chain of filters in order to apply its services. You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn’t currently a namespace configuration option (CAS, for example). Or you might want to use a customized version of a standard namespace filter, such as the UsernamePasswordAuthenticationFilter which is created by the <form-login> element, taking advantage of some of the extra configuration options which are available by using the bean explicitly. How can you do this with namespace configuration, since the filter chain is not directly exposed?

如果您以前使用過Spring Security,那麼您將知道該框架維護了一系列過濾器以便應用其服務。您可能希望將自己的過濾器新增到特定位置的堆疊,或者使用當前沒有名稱空間配置選項的Spring Security過濾器(例如,CAS)。或者您可能希望使用標準名稱空間過濾器的自定義版本,例如由<form-login>元素建立的UsernamePasswordAuthenticationFilter,利用明確使用bean可用的一些額外配置選項。如何通過名稱空間配置來完成此操作,因為過濾器鏈未直接公開?   The order of the filters is always strictly enforced when using the namespace. When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position. 使用名稱空間時,始終嚴格執行過濾器的順序。在建立應用程式上下文時,過濾器bean按名稱空間處理程式碼進行排序,標準的Spring Security過濾器在名稱空間中都有一個別名和一個眾所周知的位置。   In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context. In version 3.0+ the sorting is now done at the bean metadata level, before the classes have been instantiated. This has implications for how you add your own filters to the stack as the entire filter list must be known during the parsing of the  <http> element, so the syntax has changed slightly in 3.0. 在以前的版本中,排序發生在建立過濾器例項之後,在應用程式上下文的後處理期間。在版本3.0+中,現在在例項化類之前,在bean元資料級別完成排序。這會影響您如何將自己的過濾器新增到堆疊中,因為在解析<http>元素期間必須知道整個過濾器列表,因此語法在3.0中稍有改變。   The filters, aliases and namespace elements/attributes which create the filters are shown in  Table 6.1, “Standard Filter Aliases and Ordering”. The filters are listed in the order in which they occur in the filter chain. 表6.1“標準過濾器別名和排序”中顯示了建立過濾器的過濾器,別名和名稱空間元素/屬性。過濾器按它們在過濾器鏈中出現的順序列出。   Table 6.1. Standard Filter Aliases and Ordering(標準過濾器別名和訂購)
Alias Filter Class Namespace Element or Attribute

CHANNEL_FILTER

ChannelProcessingFilter

http/[email protected]

SECURITY_CONTEXT_FILTER

SecurityContextPersistenceFilter

http

CONCURRENT_SESSION_FILTER

ConcurrentSessionFilter

session-management/concurrency-control

HEADERS_FILTER

HeaderWriterFilter

http/headers

CSRF_FILTER

CsrfFilter

http/csrf

LOGOUT_FILTER

LogoutFilter

http/logout

X509_FILTER

X509AuthenticationFilter

http/x509

PRE_AUTH_FILTER

AbstractPreAuthenticatedProcessingFilter Subclasses

N/A

CAS_FILTER

CasAuthenticationFilter

N/A

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

session-management

EXCEPTION_TRANSLATION_FILTER

ExceptionTranslationFilter

http

FILTER_SECURITY_INTERCEPTOR

FilterSecurityInterceptor

http

SWITCH_USER_FILTER

SwitchUserFilter

N/A

 

 You can add your own filter to the stack, using the  custom-filter element and one of these names to specify the position your filter should appear at: 您可以使用custom-filter元素和其中一個名稱將自己的過濾器新增到堆疊,以指定過濾器應顯示的位置:  
<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>

<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>

You can also use the after or before attributes if you want your filter to be inserted before or after another filter in the stack. The names "FIRST" and "LAST" can be used with the position attribute to indicate that you want your filter to appear before or after the entire stack, respectively.

如果希望在堆疊中的另一個過濾器之前或之後插入過濾器,也可以使用after或before屬性。名稱“FIRST”和“LAST”可與position屬性一起使用,以指示您希望過濾器分別出現在整個堆疊之前或之後。  

If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it’s important that you don’t include the namespace versions by mistake. Remove any elements which create filters whose functionality you want to replace.

Note that you can’t replace filters which are created by the use of the <http> element itself - SecurityContextPersistenceFilterExceptionTranslationFilter or FilterSecurityInterceptor. Some other filters are added by default, but you can disable them. An AnonymousAuthenticationFilter is added by default and unless you have session-fixation protection disabled, a SessionManagementFilter will also be added to the filter chain.

如果要插入的自定義過濾器可能與名稱空間建立的標準過濾器之一佔據相同的位置,則重要的是不要錯誤地包含名稱空間版本。刪除任何建立要替換其功能的過濾器的元素。 請注意,您無法替換使用<http>元素本身建立的過濾器 - SecurityContextPersistenceFilter,ExceptionTranslationFilter或FilterSecurityInterceptor。預設情況下會新增其他一些過濾器,但您可以禁用它們。預設情況下會新增AnonymousAuthenticationFilter,除非禁用會話固定保護,否則還會將SessionManagementFilter新增到過濾器鏈中。   If you’re replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too. 如果要替換需要身份驗證入口點的名稱空間過濾器(即,未經身份驗證的使用者嘗試訪問安全資源而觸發身份驗證過程),則還需要新增自定義入口點Bean。

Setting a Custom AuthenticationEntryPoint(設定自定義AuthenticationEntryPoint)

If you aren’t using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we’ve just seen. The corresponding AuthenticationEntryPoint can be set using the entry-point-ref attribute on the <http> element.

如果您沒有使用表單登入,OpenID或通過名稱空間進行基本身份驗證,您可能需要使用傳統的bean語法定義身份驗證過濾器和入口點,並將它們連結到名稱空間,如我們剛才所見。可以使用<http>元素上的entry-point-ref屬性設定相應的AuthenticationEntryPoint。   The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax. If you aren’t familiar with authentication entry points, they are discussed in the  technical overview chapter. CAS示例應用程式是使用帶有名稱空間的自定義bean的一個很好的示例,包括此語法。如果您不熟悉身份驗證入口點,則會在技術概述一章中討論它們。