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
<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:
<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 theJSESSIONID
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:
<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.
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
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.
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>
:
<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.
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:
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.
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?
<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 |
|
|
SECURITY_CONTEXT_FILTER |
|
|
CONCURRENT_SESSION_FILTER |
|
|
HEADERS_FILTER |
|
|
CSRF_FILTER |
|
|
LOGOUT_FILTER |
|
|
X509_FILTER |
|
|
PRE_AUTH_FILTER |
|
N/A |
CAS_FILTER |
|
N/A |
FORM_LOGIN_FILTER |
|
|
BASIC_AUTH_FILTER |
|
|
SERVLET_API_SUPPORT_FILTER |
|
|
JAAS_API_SUPPORT_FILTER |
|
|
REMEMBER_ME_FILTER |
|
|
ANONYMOUS_FILTER |
|
|
SESSION_MANAGEMENT_FILTER |
|
|
EXCEPTION_TRANSLATION_FILTER |
|
|
FILTER_SECURITY_INTERCEPTOR |
|
|
SWITCH_USER_FILTER |
|
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.
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 - SecurityContextPersistenceFilter
, ExceptionTranslationFilter
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.
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.