此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.3spring-doc.cadn.net.cn

安全命名空间配置

介绍

命名空间配置从 Spring Framework 的 2.0 版开始就可用。 它允许您使用其他 XML 模式中的元素来补充传统的 Spring Bean 应用程序上下文语法。 您可以在 Spring 参考文档中找到更多信息。 命名空间元素可以简单地用于允许以更简洁的方式配置单个 bean,或者更强大地定义一种替代配置语法,该语法更紧密地匹配问题域,并向用户隐藏底层复杂性。 一个简单的元素可能会掩盖一个事实,即多个 bean 和处理步骤被添加到应用程序上下文中。 例如,将 security 名称空间中的以下元素添加到应用程序上下文将启动嵌入式 LDAP 服务器,以便在应用程序中进行测试使用:spring-doc.cadn.net.cn

<security:ldap-server />

这比连接等效的 Apache Directory Server Bean 要简单得多。 最常见的替代配置要求由ldap-server元素,用户无需担心他们需要创建哪些 bean 以及 bean 属性名称是什么。[1].]. 在编辑应用程序上下文文件时,使用良好的 XML 编辑器应提供有关可用属性和元素的信息。 我们建议您试用带有 Spring Tools 的 Eclipse IDE,因为它具有使用标准 Spring 命名空间的特殊功能。spring-doc.cadn.net.cn

要开始在应用程序上下文中使用安全命名空间,您需要具有spring-security-configjar 中。 然后,您需要做的就是将 schema 声明添加到您的应用程序上下文文件中:spring-doc.cadn.net.cn

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security
		https://www.springframework.org/schema/security/spring-security.xsd">
	...
</beans>

在您将看到的许多示例中(以及示例应用程序),我们经常使用“security”而不是“beans”作为默认命名空间,这意味着我们可以省略所有安全命名空间元素上的前缀,从而使内容更易于阅读。 如果您将应用程序上下文划分为单独的文件,并且大部分安全性配置都在其中一个文件中,则可能还需要执行此作。 然后,您的安全应用程序上下文文件将按如下方式启动spring-doc.cadn.net.cn

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security
		https://www.springframework.org/schema/security/spring-security.xsd">
	...
</beans:beans>

我们假设从现在开始,本章将使用此语法。spring-doc.cadn.net.cn

命名空间的设计

命名空间旨在捕获框架的最常见用途,并提供简化而简洁的语法,以便在应用程序中启用它们。 该设计基于框架内的大规模依赖项,可以分为以下几个方面:spring-doc.cadn.net.cn

  • Web/HTTP 安全 - 最复杂的部分。 设置用于应用框架身份验证机制的过滤器和相关服务 Bean,以保护 URL、呈现登录页和错误页等等。spring-doc.cadn.net.cn

  • 业务对象(方法)安全性 - 用于保护服务层的选项。spring-doc.cadn.net.cn

  • AuthenticationManager - 处理来自框架其他部分的身份验证请求。spring-doc.cadn.net.cn

  • AccessDecisionManager - 为 Web 和方法安全提供访问决策。 将注册一个默认的,但你也可以选择使用自定义的,使用普通的 Spring bean 语法声明。spring-doc.cadn.net.cn

  • AuthenticationProviders - 身份验证管理器对用户进行身份验证的机制。 名称空间提供了对多个标准选项的支持,还提供了一种添加使用传统语法声明的自定义 bean 的方法。spring-doc.cadn.net.cn

  • UserDetailsService - 与身份验证提供程序密切相关,但通常其他 bean 也需要。spring-doc.cadn.net.cn

我们将在以下部分中了解如何配置这些 API。spring-doc.cadn.net.cn

Security Namespace Configuration 入门

在本节中,我们将了解如何构建命名空间配置以使用框架的一些主要功能。 假设您最初希望尽快启动并运行,并通过几次测试登录向现有 Web 应用程序添加身份验证支持和访问控制。 然后,我们将了解如何转换为针对数据库或其他安全存储库进行身份验证。 在后面的部分中,我们将介绍更高级的命名空间配置选项。spring-doc.cadn.net.cn

web.xml配置

您需要做的第一件事是将以下过滤器声明添加到您的web.xml文件:spring-doc.cadn.net.cn

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

这为 Spring Security Web 基础结构提供了一个钩子。DelegatingFilterProxy是一个 Spring Framework 类,它委托给一个过滤器实现,该实现在应用程序上下文中定义为 Spring Bean。 在这种情况下,该 Bean 被命名为“springSecurityFilterChain”,这是由名称空间创建的用于处理 Web 安全性的内部基础结构 Bean。 请注意,您自己不应使用此 bean 名称。 将此 API 添加到您的web.xml,即可开始编辑应用程序上下文文件。 Web 安全服务使用<http>元素。spring-doc.cadn.net.cn

最小 <http> 配置

启用 Web 安全只需从spring-doc.cadn.net.cn

<http>
<intercept-url pattern="/**" access="hasRole('USER')" />
<form-login />
<logout />
</http>

这表示我们希望应用程序中的所有 URL 都得到保护,这需要角色ROLE_USER要访问它们,我们希望使用带有用户名和密码的表单登录应用程序,并且我们希望注册一个注销 URL,这将允许我们注销应用程序。<http>元素是所有与 Web 相关的命名空间功能的父级。 这<intercept-url>元素定义一个pattern该 URL 与 Ant Path 样式语法的传入请求的 URL 进行匹配[2]有关实际如何执行对战的更多详细信息。 您还可以使用正则表达式匹配作为替代方法(有关更多详细信息,请参阅 namespace appendix)。 这access属性定义与给定模式匹配的请求的访问要求。 使用默认配置时,这通常是一个以逗号分隔的角色列表,必须允许用户发出请求。 前缀 “ROLE_” 是一个标记,表示应该与用户的权限进行简单比较。 换句话说,应该使用正常的基于角色的检查。 Spring Security 中的访问控制不仅限于使用简单的角色(因此使用前缀来区分不同类型的安全属性)。 我们稍后要看解释是怎样变化的[3]. 在 Spring Security 3.0 中,还可以使用 EL 表达式填充该属性。spring-doc.cadn.net.cn

您可以使用多个<intercept-url>元素来定义不同 URL 集的不同访问要求,但将按列出的顺序对它们进行评估,并使用第一个匹配项。 因此,您必须将最具体的匹配项放在顶部。 您还可以添加method属性将匹配限制为特定的 HTTP 方法 (GET,POST,PUT等)。spring-doc.cadn.net.cn

要添加一些用户,您可以直接在命名空间中定义一组测试数据:spring-doc.cadn.net.cn

<authentication-manager>
<authentication-provider>
	<user-service>
	<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
	NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
	in samples easier. Normally passwords should be hashed using BCrypt -->
	<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
	</user-service>
</authentication-provider>
</authentication-manager>

这是存储相同密码的安全方法的示例。 密码以{bcrypt}指示DelegatingPasswordEncoder,它支持任何已配置的PasswordEncoder为了匹配,密码使用 BCrypt 进行哈希处理:spring-doc.cadn.net.cn

<authentication-manager>
<authentication-provider>
	<user-service>
	<user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
			authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
			authorities="ROLE_USER" />
	<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
	<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
	</user-service>
</authentication-provider>
</authentication-manager>

如果您熟悉框架的 pre-namespace 版本,您可能已经可以大致猜到这里发生了什么。 这<http>元素负责创建一个FilterChainProxy以及它使用的 filter bean。 由于过滤器位置是预定义的,因此过滤器顺序不正确等常见问题不再是问题。spring-doc.cadn.net.cn

<authentication-provider>元素会创建一个DaoAuthenticationProviderbean 和<user-service>元素会创建一个InMemoryDaoImpl. 都authentication-provider元素必须是<authentication-manager>元素,它会创建一个ProviderManager并向其注册身份验证提供程序。 您可以在名称空间附录中找到有关创建的 bean 的更多详细信息。 如果您想开始了解框架中的重要类是什么以及它们是如何使用的,特别是如果您想稍后自定义内容,那么值得交叉检查这一点。spring-doc.cadn.net.cn

上面的配置定义了两个用户,他们的密码和他们在应用程序中的角色(将用于访问控制)。 还可以使用properties属性user-service. 请参阅 内存身份验证 有关文件格式的更多详细信息。 使用<authentication-provider>元素表示 Authentication Manager 将使用用户信息来处理身份验证请求。 您可以有多个<authentication-provider>元素来定义不同的身份验证源,并且将依次访问每个元素。spring-doc.cadn.net.cn

此时,您应该能够启动您的应用程序,并且需要登录才能继续。 尝试一下,或者尝试使用项目附带的 “tutorial” 示例应用程序进行试验。spring-doc.cadn.net.cn

设置默认登录后目标

如果尝试访问受保护资源时未提示表单登录,则default-target-url选项开始发挥作用。 这是用户成功登录后将转到的 URL,默认为 “/”。 您还可以通过设置always-use-default-target属性设置为 “true”。 如果您的应用程序始终要求用户从 “home” 页面开始,则这非常有用,例如:spring-doc.cadn.net.cn

<http pattern="/login.htm*" security="none"/>
<http use-expressions="false">
<intercept-url pattern='/**' access='ROLE_USER' />
<form-login login-page='/login.htm' default-target-url='/home.htm'
		always-use-default-target='true' />
</http>

要对目标进行更多控制,您可以使用authentication-success-handler-ref属性作为default-target-url. 引用的 Bean 应该是AuthenticationSuccessHandler.spring-doc.cadn.net.cn

高级 Web 功能

添加您自己的过滤器

如果您以前使用过 Spring Security,您将知道该框架维护了一个过滤器链以应用其服务。 您可能希望将自己的过滤器添加到特定位置的堆栈中,或者使用当前没有命名空间配置选项(例如 CAS)的 Spring Security 过滤器。 或者,您可能希望使用标准命名空间过滤器的自定义版本,例如UsernamePasswordAuthenticationFilter它由<form-login>元素,利用一些额外的配置选项,这些选项可以通过显式使用 bean 来获得。 既然过滤器链没有直接公开,你怎么能用命名空间配置来做到这一点呢?spring-doc.cadn.net.cn

使用命名空间时,始终严格执行过滤器的顺序。 在创建应用程序上下文时,过滤器 bean 按名称空间处理代码排序,并且标准 Spring Security 过滤器在名称空间中都有一个别名和一个众所周知的位置。spring-doc.cadn.net.cn

在以前的版本中,排序是在创建 filter 实例之后,在应用程序上下文的后处理期间进行的。 在 3.0+ 版本中,排序现在是在 bean 元数据级别完成的,在实例化类之前。 这对如何将自己的过滤器添加到堆栈中有影响,因为在解析<http>元素,因此语法在 3.0 中略有变化。spring-doc.cadn.net.cn

创建过滤器的过滤器、别名和命名空间元素/属性显示在标准过滤器别名和排序中。 筛选器按它们在筛选器链中出现的顺序列出。spring-doc.cadn.net.cn

表 1.标准过滤器别名和排序
别名 Filter 类 命名空间元素或属性

DISABLE_ENCODE_URL_FILTERspring-doc.cadn.net.cn

DisableEncodeUrlFilterspring-doc.cadn.net.cn

http@disable-url-rewritingspring-doc.cadn.net.cn

FORCE_EAGER_SESSION_FILTERspring-doc.cadn.net.cn

ForceEagerSessionCreationFilterspring-doc.cadn.net.cn

http@create-session="ALWAYS"spring-doc.cadn.net.cn

CHANNEL_FILTERspring-doc.cadn.net.cn

ChannelProcessingFilterspring-doc.cadn.net.cn

http/intercept-url@requires-channelspring-doc.cadn.net.cn

SECURITY_CONTEXT_FILTERspring-doc.cadn.net.cn

SecurityContextPersistenceFilterspring-doc.cadn.net.cn

httpspring-doc.cadn.net.cn

CONCURRENT_SESSION_FILTERspring-doc.cadn.net.cn

ConcurrentSessionFilterspring-doc.cadn.net.cn

session-management/concurrency-controlspring-doc.cadn.net.cn

HEADERS_FILTERspring-doc.cadn.net.cn

HeaderWriterFilterspring-doc.cadn.net.cn

http/headersspring-doc.cadn.net.cn

CSRF_FILTERspring-doc.cadn.net.cn

CsrfFilterspring-doc.cadn.net.cn

http/csrfspring-doc.cadn.net.cn

LOGOUT_FILTERspring-doc.cadn.net.cn

LogoutFilterspring-doc.cadn.net.cn

http/logoutspring-doc.cadn.net.cn

X509_FILTERspring-doc.cadn.net.cn

X509AuthenticationFilterspring-doc.cadn.net.cn

http/x509spring-doc.cadn.net.cn

PRE_AUTH_FILTERspring-doc.cadn.net.cn

AbstractPreAuthenticatedProcessingFilterspring-doc.cadn.net.cn

不适用spring-doc.cadn.net.cn

CAS_FILTERspring-doc.cadn.net.cn

CasAuthenticationFilterspring-doc.cadn.net.cn

不适用spring-doc.cadn.net.cn

FORM_LOGIN_FILTERspring-doc.cadn.net.cn

UsernamePasswordAuthenticationFilterspring-doc.cadn.net.cn

http/form-loginspring-doc.cadn.net.cn

BASIC_AUTH_FILTERspring-doc.cadn.net.cn

BasicAuthenticationFilterspring-doc.cadn.net.cn

http/http-basicspring-doc.cadn.net.cn

SERVLET_API_SUPPORT_FILTERspring-doc.cadn.net.cn

SecurityContextHolderAwareRequestFilterspring-doc.cadn.net.cn

http/@servlet-api-provisionspring-doc.cadn.net.cn

JAAS_API_SUPPORT_FILTERspring-doc.cadn.net.cn

JaasApiIntegrationFilterspring-doc.cadn.net.cn

http/@jaas-api-provisionspring-doc.cadn.net.cn

REMEMBER_ME_FILTERspring-doc.cadn.net.cn

RememberMeAuthenticationFilterspring-doc.cadn.net.cn

http/remember-mespring-doc.cadn.net.cn

ANONYMOUS_FILTERspring-doc.cadn.net.cn

AnonymousAuthenticationFilterspring-doc.cadn.net.cn

http/anonymousspring-doc.cadn.net.cn

SESSION_MANAGEMENT_FILTERspring-doc.cadn.net.cn

SessionManagementFilterspring-doc.cadn.net.cn

session-managementspring-doc.cadn.net.cn

EXCEPTION_TRANSLATION_FILTERspring-doc.cadn.net.cn

ExceptionTranslationFilterspring-doc.cadn.net.cn

httpspring-doc.cadn.net.cn

FILTER_SECURITY_INTERCEPTORspring-doc.cadn.net.cn

FilterSecurityInterceptorspring-doc.cadn.net.cn

httpspring-doc.cadn.net.cn

SWITCH_USER_FILTERspring-doc.cadn.net.cn

SwitchUserFilterspring-doc.cadn.net.cn

不适用spring-doc.cadn.net.cn

您可以使用custom-filter元素和以下名称之一来指定过滤器应显示的位置:spring-doc.cadn.net.cn

<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>

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

您还可以使用afterbeforeattributes (如果您希望将筛选条件插入到堆栈中的另一个筛选条件之前或之后)。 名称 “FIRST” 和 “LAST” 可以与position属性来指示您希望筛选条件分别显示在整个堆栈之前或之后。spring-doc.cadn.net.cn

避免过滤器位置冲突

如果要插入的自定义筛选器可能与命名空间创建的标准筛选器之一占据相同的位置,则请务必不要错误地包含命名空间版本。 删除任何创建要替换其功能的过滤器的元素。spring-doc.cadn.net.cn

请注意,您无法替换通过使用<http>元素本身 -SecurityContextPersistenceFilter,ExceptionTranslationFilterFilterSecurityInterceptor. 默认情况下会添加一些其他筛选器,但您可以禁用它们。 一AnonymousAuthenticationFilter默认添加,除非您禁用了会话固定保护,否则SessionManagementFilter也会被添加到过滤器链中。spring-doc.cadn.net.cn

如果要替换需要身份验证入口点的名称空间过滤器(即,身份验证过程是由未经身份验证的用户尝试访问受保护资源触发的),则还需要添加自定义入口点 Bean。spring-doc.cadn.net.cn

方法安全性

从版本 2.0 开始, Spring Security 大大改进了对向服务层方法添加安全性的支持。 它支持 JSR-250 注释安全性以及框架的原始@Secured注解。 从 3.0 开始,您还可以使用新的基于表达式的注释。 您可以使用intercept-methods元素来装饰 bean 声明,或者你可以使用 AspectJ 样式的切入点在整个服务层中保护多个 bean。spring-doc.cadn.net.cn

默认的 AccessDecisionManager

本节假定您对 Spring Security 中访问控制的底层架构有一定的了解。 如果你不这样做,你可以跳过它,稍后再回来,因为本节只与需要进行一些自定义以使用不仅仅是简单的基于角色的安全性的人真正相关。spring-doc.cadn.net.cn

当您使用命名空间配置时,默认的AccessDecisionManager会自动为您注册,并将用于根据您在intercept-urlprotect-pointcut声明(如果您使用的是 Annotation Secured 方法,则在 annotations 中)。spring-doc.cadn.net.cn

默认策略是使用AffirmativeBased AccessDecisionManager替换为RoleVoter以及一个AuthenticatedVoter. 您可以在授权章节中了解有关这些内容的更多信息。spring-doc.cadn.net.cn

自定义 AccessDecisionManager

如果您需要使用更复杂的访问控制策略,那么很容易为方法和 Web 安全设置替代方案。spring-doc.cadn.net.cn

为了方法安全性,您可以通过设置access-decision-manager-ref属性global-method-securityid的适当AccessDecisionManagerbean 中:spring-doc.cadn.net.cn

<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
...
</global-method-security>

Web 安全性的语法是相同的,但在http元素:spring-doc.cadn.net.cn

<http access-decision-manager-ref="myAccessDecisionManagerBean">
...
</http>

1. 您可以了解有关ldap-serverxref:servlet/authentication/unpwd/ldap.adoc#servlet-authentication-ldap[LDAP 身份验证
2. 参见 xref:servlet/exploits/firewall.adoc#servlet-httpfirewall['HttpFirewall'
3. 对access属性取决于所使用的 AccessDecisionManager 的实现。