对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

自 Spring Framework 2.0 版以来,命名空间配置一直可用。 它允许您使用其他 XML 模式中的元素来补充传统的 Spring Bean 应用程序上下文语法。 您可以在 Spring 参考文档中找到更多信息。 您可以使用命名空间元素来更简洁地配置单个 Bean,或者更强大地定义一种替代配置语法,该语法更接近于问题域,并对用户隐藏底层复杂性。 一个简单的元素可以隐藏将多个 Bean 和处理步骤添加到应用程序上下文中的事实。 例如,将以下元素从命名空间添加到应用程序上下文将启动嵌入式 LDAP 服务器,以便在应用程序内测试使用:securitySpring中文文档

<security:ldap-server />

这比连接等效的 Apache Directory Server Bean 要简单得多。 元素上的属性支持最常见的替代配置要求,并且用户无需担心他们需要创建哪些 Bean 以及 Bean 属性名称是什么。 您可以在 LDAP 身份验证一章中找到有关该元素使用的更多信息。 一个好的 XML 编辑器在编辑应用程序上下文文件时,应该提供有关可用属性和元素的信息。 我们建议您尝试 Spring 工具套件,因为它具有使用标准 Spring 命名空间的特殊功能。ldap-serverldap-serverSpring中文文档

若要开始在应用程序上下文中使用命名空间,请将 jar 添加到类路径中。 然后,您需要做的就是将架构声明添加到应用程序上下文文件中:securityspring-security-configSpring中文文档

<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>

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

<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中文文档

命名空间的设计

命名空间旨在捕获框架的最常见用法,并提供简化和简洁的语法,以便在应用程序中启用它们。 该设计基于框架内的大规模依赖关系,可分为以下几个方面:Spring中文文档

  • Web/HTTP 安全是最复杂的部分。 它设置过滤器和相关服务 Bean,用于应用框架身份验证机制、保护 URL、呈现登录和错误页面等。Spring中文文档

  • 业务对象(方法)安全性定义用于保护服务层的选项。Spring中文文档

  • AuthenticationManager 处理来自框架其他部分的身份验证请求。Spring中文文档

  • AccessDecisionManager 提供 Web 和方法安全性的访问决策。 注册了一个默认的,但你可以选择使用一个自定义的,用普通的Spring bean语法声明。Spring中文文档

  • AuthenticationProvider 实例提供身份验证管理器对用户进行身份验证所依据的机制。 命名空间提供了对多个标准选项的支持,以及添加使用传统语法声明的自定义 Bean 的方法。Spring中文文档

  • UserDetailsService 与身份验证提供程序密切相关,但其他 Bean 通常也需要它。Spring中文文档

我们将在以下各节中了解如何配置这些内容。Spring中文文档

安全命名空间配置入门

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

web.xml配置

您需要做的第一件事是将以下筛选器声明添加到您的文件中:web.xmlSpring中文文档

<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>

DelegatingFilterProxy是一个 Spring Framework 类,它委托给在应用程序上下文中定义为 Spring Bean 的过滤器实现。 在本例中,bean 被命名为 ,这是由命名空间创建的用于处理 Web 安全性的内部基础结构 bean。 在本例中,Bean 被命名为“springSecurityFilterChain”,它是命名空间创建的用于处理 Web 安全性的内部基础架构 Bean。 请注意,您自己不应使用此 Bean 名称。 将此 Bean 添加到 后,就可以开始编辑应用程序上下文文件了。 Web 安全服务由元素配置。springSecurityFilterChainweb.xml<http>Spring中文文档

最小 <http> 配置

要启用 Web 安全性,您需要以下配置:Spring中文文档

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

该列表说我们想要:Spring中文文档

该元素是所有与 Web 相关的命名空间功能的父元素。 该元素定义了一个 ,该 与使用 Ant 路径语法的传入请求的 URL 匹配。有关如何实际执行匹配的更多详细信息,请参阅 HttpFirewall 部分。 还可以使用正则表达式匹配作为替代方法(有关详细信息,请参阅命名空间附录)。 该属性定义与给定模式匹配的请求的访问要求。 使用默认配置时,这通常是以逗号分隔的角色列表,必须允许用户发出请求。 前缀是一个标记,指示应与用户的权限进行简单的比较。 换句话说,应使用基于角色的常规检查。 Spring Security 中的访问控制不仅限于使用简单角色(因此使用前缀来区分不同类型的安全属性)。 我们稍后会看到解释如何变化。属性中逗号分隔值的解释取决于使用的 AccessDecisionManager 实现。 从 Spring Security 3.0 开始,您还可以使用 EL 表达式填充属性。<http><intercept-url>patternaccessROLE_accessSpring中文文档

您可以使用多个元素为不同的 URL 集定义不同的访问要求,但这些元素将按列出的顺序进行评估,并使用第一个匹配项。 因此,您必须将最具体的匹配项放在顶部。 您还可以添加一个属性来限制与特定 HTTP 方法(、、、等)的匹配。<intercept-url>methodGETPOSTPUTSpring中文文档

若要添加用户,可以直接在命名空间中定义一组测试数据:Spring中文文档

<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>

上面的清单显示了存储相同密码的安全方法的示例。 密码以 to 指示为前缀,该指示支持任何配置为匹配的密码,使用 BCrypt 对密码进行哈希处理:{bcrypt}DelegatingPasswordEncoderPasswordEncoderSpring中文文档

<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>

该元素负责创建它使用的过滤 Bean 和过滤 Bean。 以前的常见问题(例如不正确的过滤器排序)不再是问题,因为过滤器位置是预定义的。<http>FilterChainProxySpring中文文档

该元素创建一个 bean,该元素创建一个 . 所有元素都必须是该元素的子元素,该元素创建一个并向其注册身份验证提供程序。 您可以在命名空间附录中找到有关创建的 Bean 的更多详细信息。 如果你想开始了解框架中的重要类是什么以及它们是如何使用的,你应该交叉检查这个附录,特别是如果你想以后自定义一些东西。<authentication-provider>DaoAuthenticationProvider<user-service>InMemoryDaoImplauthentication-provider<authentication-manager>ProviderManagerSpring中文文档

上述配置定义了两个用户、他们的密码和他们在应用程序中的角色(用于访问控制)。 还可以通过设置元素上的属性从标准属性文件加载用户信息。 有关文件格式的更多详细信息,请参阅有关内存中身份验证的部分。 使用该元素意味着身份验证管理器使用用户信息来处理身份验证请求。 您可以使用多个元素来定义不同的身份验证源。依次咨询每个人。propertiesuser-service<authentication-provider><authentication-provider>Spring中文文档

此时,您应该能够启动应用程序,并且需要登录才能继续。 尝试一下,或者尝试使用项目附带的“教程”示例应用程序进行试验。Spring中文文档

设置默认登录后目标

如果尝试访问受保护资源时未提示表单登录,则该选项将发挥作用。 这是用户成功登录后转到的 URL。它默认为 。 您还可以通过将属性设置为 来配置内容,以便用户始终最终访问此页面(无论登录是“按需”还是他们明确选择登录)。 如果应用程序始终要求用户从“主页”页面启动,这将非常有用,例如:default-target-url/always-use-default-targettrueSpring中文文档

<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>

为了更好地控制目标,可以使用该属性作为 的替代项。 引用的 Bean 应是 的实例。authentication-success-handler-refdefault-target-urlAuthenticationSuccessHandlerSpring中文文档

您可以使用多个元素为不同的 URL 集定义不同的访问要求,但这些元素将按列出的顺序进行评估,并使用第一个匹配项。 因此,您必须将最具体的匹配项放在顶部。 您还可以添加一个属性来限制与特定 HTTP 方法(、、、等)的匹配。<intercept-url>methodGETPOSTPUTSpring中文文档

高级 Web 功能

本节介绍超出基础知识的各种功能。Spring中文文档

添加您自己的过滤器

如果您以前使用过 Spring Security,您就会知道该框架维护着用于应用其服务的过滤器链。 您可能希望将自己的过滤器添加到特定位置的堆栈中,或者使用当前没有命名空间配置选项(例如 CAS)的 Spring Security 过滤器。 或者,您可能希望使用标准命名空间过滤器的定制版本,例如 (由元素创建)来利用显式使用 Bean 时可用的一些额外配置选项。 由于筛选器链不直接公开,因此如何使用命名空间配置执行此操作?UsernamePasswordAuthenticationFilter<form-login>Spring中文文档

使用命名空间时,始终严格执行筛选器的顺序。 在创建应用程序上下文时,筛选器 Bean 按命名空间处理代码排序,并且每个标准 Spring Security 筛选器在命名空间中都有一个别名和一个已知位置。Spring中文文档

在以前的版本中,排序是在创建筛选器实例之后,在应用程序上下文的后处理期间进行的。 在 V3.0+ 中,排序现在在 Bean 元数据级别完成,然后再实例化类。 这对如何将自己的过滤器添加到堆栈中具有重要意义,因为在解析元素期间必须知道整个过滤器列表,因此语法在 3.0 中略有变化。<http>Spring中文文档

下表显示了创建筛选器的筛选器、别名以及命名空间元素和属性,按它们在筛选器链中出现的顺序显示:Spring中文文档

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

DISABLE_ENCODE_URL_FILTERSpring中文文档

DisableEncodeUrlFilterSpring中文文档

http@disable-url-rewritingSpring中文文档

FORCE_EAGER_SESSION_FILTERSpring中文文档

ForceEagerSessionCreationFilterSpring中文文档

http@create-session="ALWAYS"Spring中文文档

CHANNEL_FILTERSpring中文文档

ChannelProcessingFilterSpring中文文档

http/intercept-url@requires-channelSpring中文文档

SECURITY_CONTEXT_FILTERSpring中文文档

SecurityContextPersistenceFilterSpring中文文档

httpSpring中文文档

CONCURRENT_SESSION_FILTERSpring中文文档

ConcurrentSessionFilterSpring中文文档

session-management/concurrency-controlSpring中文文档

HEADERS_FILTERSpring中文文档

HeaderWriterFilterSpring中文文档

http/headersSpring中文文档

CSRF_FILTERSpring中文文档

CsrfFilterSpring中文文档

http/csrfSpring中文文档

LOGOUT_FILTERSpring中文文档

LogoutFilterSpring中文文档

http/logoutSpring中文文档

X509_FILTERSpring中文文档

X509AuthenticationFilterSpring中文文档

http/x509Spring中文文档

PRE_AUTH_FILTERSpring中文文档

AbstractPreAuthenticatedProcessingFilterSpring中文文档

不适用Spring中文文档

CAS_FILTERSpring中文文档

CasAuthenticationFilterSpring中文文档

不适用Spring中文文档

FORM_LOGIN_FILTERSpring中文文档

UsernamePasswordAuthenticationFilterSpring中文文档

http/form-loginSpring中文文档

BASIC_AUTH_FILTERSpring中文文档

BasicAuthenticationFilterSpring中文文档

http/http-basicSpring中文文档

SERVLET_API_SUPPORT_FILTERSpring中文文档

SecurityContextHolderAwareRequestFilterSpring中文文档

http/@servlet-api-provisionSpring中文文档

JAAS_API_SUPPORT_FILTERSpring中文文档

JaasApiIntegrationFilterSpring中文文档

http/@jaas-api-provisionSpring中文文档

REMEMBER_ME_FILTERSpring中文文档

RememberMeAuthenticationFilterSpring中文文档

http/remember-meSpring中文文档

ANONYMOUS_FILTERSpring中文文档

AnonymousAuthenticationFilterSpring中文文档

http/anonymousSpring中文文档

SESSION_MANAGEMENT_FILTERSpring中文文档

SessionManagementFilterSpring中文文档

session-managementSpring中文文档

EXCEPTION_TRANSLATION_FILTERSpring中文文档

ExceptionTranslationFilterSpring中文文档

httpSpring中文文档

FILTER_SECURITY_INTERCEPTORSpring中文文档

FilterSecurityInterceptorSpring中文文档

httpSpring中文文档

SWITCH_USER_FILTERSpring中文文档

SwitchUserFilterSpring中文文档

不适用Spring中文文档

您可以使用元素和以下名称之一将自己的筛选器添加到堆栈中,以指定筛选器应显示的位置:custom-filterSpring中文文档

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

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

如果您希望将筛选器插入在堆栈中的另一个筛选器之前或之后,也可以使用 or 属性。 您可以将 和 与属性一起使用,以指示您希望筛选条件分别显示在整个堆栈之前或之后。afterbeforeFIRSTLASTpositionSpring中文文档

避免过滤器位置冲突

如果插入的自定义筛选器可能与命名空间创建的标准筛选器之一占据相同的位置,则不应错误地包含命名空间版本。 删除创建要替换其功能的筛选器的所有元素。Spring中文文档

请注意,您不能替换使用元素本身创建的筛选器:、 或 。 默认情况下,会添加 an,除非禁用会话固定保护,否则还会将 a 添加到筛选器链中。<http>SecurityContextPersistenceFilterExceptionTranslationFilterFilterSecurityInterceptorAnonymousAuthenticationFilterSessionManagementFilterSpring中文文档

如果替换需要身份验证入口点的命名空间过滤器(即,由未经身份验证的用户尝试访问受保护资源触发身份验证过程的位置),则还需要添加自定义入口点 Bean。Spring中文文档

在以前的版本中,排序是在创建筛选器实例之后,在应用程序上下文的后处理期间进行的。 在 V3.0+ 中,排序现在在 Bean 元数据级别完成,然后再实例化类。 这对如何将自己的过滤器添加到堆栈中具有重要意义,因为在解析元素期间必须知道整个过滤器列表,因此语法在 3.0 中略有变化。<http>Spring中文文档

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

DISABLE_ENCODE_URL_FILTERSpring中文文档

DisableEncodeUrlFilterSpring中文文档

http@disable-url-rewritingSpring中文文档

FORCE_EAGER_SESSION_FILTERSpring中文文档

ForceEagerSessionCreationFilterSpring中文文档

http@create-session="ALWAYS"Spring中文文档

CHANNEL_FILTERSpring中文文档

ChannelProcessingFilterSpring中文文档

http/intercept-url@requires-channelSpring中文文档

SECURITY_CONTEXT_FILTERSpring中文文档

SecurityContextPersistenceFilterSpring中文文档

httpSpring中文文档

CONCURRENT_SESSION_FILTERSpring中文文档

ConcurrentSessionFilterSpring中文文档

session-management/concurrency-controlSpring中文文档

HEADERS_FILTERSpring中文文档

HeaderWriterFilterSpring中文文档

http/headersSpring中文文档

CSRF_FILTERSpring中文文档

CsrfFilterSpring中文文档

http/csrfSpring中文文档

LOGOUT_FILTERSpring中文文档

LogoutFilterSpring中文文档

http/logoutSpring中文文档

X509_FILTERSpring中文文档

X509AuthenticationFilterSpring中文文档

http/x509Spring中文文档

PRE_AUTH_FILTERSpring中文文档

AbstractPreAuthenticatedProcessingFilterSpring中文文档

不适用Spring中文文档

CAS_FILTERSpring中文文档

CasAuthenticationFilterSpring中文文档

不适用Spring中文文档

FORM_LOGIN_FILTERSpring中文文档

UsernamePasswordAuthenticationFilterSpring中文文档

http/form-loginSpring中文文档

BASIC_AUTH_FILTERSpring中文文档

BasicAuthenticationFilterSpring中文文档

http/http-basicSpring中文文档

SERVLET_API_SUPPORT_FILTERSpring中文文档

SecurityContextHolderAwareRequestFilterSpring中文文档

http/@servlet-api-provisionSpring中文文档

JAAS_API_SUPPORT_FILTERSpring中文文档

JaasApiIntegrationFilterSpring中文文档

http/@jaas-api-provisionSpring中文文档

REMEMBER_ME_FILTERSpring中文文档

RememberMeAuthenticationFilterSpring中文文档

http/remember-meSpring中文文档

ANONYMOUS_FILTERSpring中文文档

AnonymousAuthenticationFilterSpring中文文档

http/anonymousSpring中文文档

SESSION_MANAGEMENT_FILTERSpring中文文档

SessionManagementFilterSpring中文文档

session-managementSpring中文文档

EXCEPTION_TRANSLATION_FILTERSpring中文文档

ExceptionTranslationFilterSpring中文文档

httpSpring中文文档

FILTER_SECURITY_INTERCEPTORSpring中文文档

FilterSecurityInterceptorSpring中文文档

httpSpring中文文档

SWITCH_USER_FILTERSpring中文文档

SwitchUserFilterSpring中文文档

不适用Spring中文文档

避免过滤器位置冲突

如果插入的自定义筛选器可能与命名空间创建的标准筛选器之一占据相同的位置,则不应错误地包含命名空间版本。 删除创建要替换其功能的筛选器的所有元素。Spring中文文档

请注意,您不能替换使用元素本身创建的筛选器:、 或 。 默认情况下,会添加 an,除非禁用会话固定保护,否则还会将 a 添加到筛选器链中。<http>SecurityContextPersistenceFilterExceptionTranslationFilterFilterSecurityInterceptorAnonymousAuthenticationFilterSessionManagementFilterSpring中文文档

方法安全性

从 2.0 版开始,Spring Security 对向服务层方法添加安全性提供了大量支持。 它提供了对 JSR-250 注解安全性以及框架原始注解的支持。 从 3.0 版开始,您还可以使用基于表达式的注释。 您可以将安全性应用于单个 Bean(通过使用元素来装饰 Bean 声明),也可以使用 AspectJ 样式的切入点来保护整个服务层中的多个 Bean。@Securedintercept-methodsSpring中文文档

默认的 AccessDecisionManager

本节假定您对 Spring Security 中访问控制的底层架构有一定的了解。 如果没有,可以跳过它,稍后再回来,因为本节仅与需要进行一些自定义以使用简单的基于角色的安全性的用户相关。Spring中文文档

使用命名空间配置时,将自动为您注册一个默认实例,并用于根据您在 和 声明中指定的访问属性(以及注释,如果使用注释来保护方法),对方法调用和 Web URL 访问做出访问决策。AccessDecisionManagerintercept-urlprotect-pointcutSpring中文文档

默认策略是将 an 与 a 和 . 您可以在授权一章中找到有关这些内容的更多信息。AffirmativeBasedAccessDecisionManagerRoleVoterAuthenticatedVoterSpring中文文档

自定义 AccessDecisionManager

如果需要使用更复杂的访问控制策略,可以同时设置方法和 Web 安全性的替代方法。Spring中文文档

为了方法安全性,您可以通过在应用程序上下文中将属性设置为相应的 Bean 来实现:access-decision-manager-refglobal-method-securityidAccessDecisionManagerSpring中文文档

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

Web Security 的语法是相同的,但属性位于元素上:httpSpring中文文档

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