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/intercept-url@requires-channel

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的一个很好的示例,包括此语法。如果您不熟悉身份验证入口点,则会在技术概述一章中讨论它们。
上一篇:python列表生成式


下一篇:Quick-cocos2d-x v3.3 SocketTCP链接(转)