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

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

示例包括 X.509、Siteminder 和运行应用程序的 Java EE 容器的认证。 使用预身份验证时,Spring Security 必须Spring中文文档

详细信息将取决于外部身份验证机制。 在 X.509 的情况下,用户可以通过其证书信息来标识,如果 Siteminder 可以通过 HTTP 请求标头来标识。 如果依赖于容器身份验证,则将通过对传入的 HTTP 请求调用该方法来识别用户。 在某些情况下,外部机制可能会为用户提供角色/权限信息,但在其他情况下,权限必须从单独的来源获取,例如 .getUserPrincipal()UserDetailsServiceSpring中文文档

预身份验证框架类

由于大多数预身份验证机制都遵循相同的模式,因此 Spring Security 具有一组类,这些类为实现预身份验证身份验证提供程序提供了一个内部框架。 这消除了重复,并允许以结构化的方式添加新的实现,而不必从头开始编写所有内容。 如果要使用 X.509 身份验证之类的东西,则无需了解这些类,因为它已经具有更易于使用和入门的命名空间配置选项。 如果您需要使用显式 Bean 配置,或者计划编写自己的实现,那么了解所提供的实现的工作方式将很有用。 您将在 . 我们在这里只提供了一个大纲,所以你应该在适当的时候查阅Javadoc和源代码。org.springframework.security.web.authentication.preauthSpring中文文档

AbstractPreAuthenticatedProcessingFilter

此类将检查安全上下文的当前内容,如果为空,它将尝试从 HTTP 请求中提取用户信息并将其提交给 . 子类重写以下方法来获取此信息:AuthenticationManagerSpring中文文档

覆盖 AbstractPreAuthenticatedProcessingFilter
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);

protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?

protected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?

调用这些后,筛选器将创建一个包含返回数据的数据并提交进行身份验证。 这里的“身份验证”,实际上只是意味着进一步处理以加载用户的权限,但遵循标准的Spring Security身份验证架构。PreAuthenticatedAuthenticationTokenSpring中文文档

与其他Spring Security身份验证过滤器一样,预身份验证过滤器具有一个属性,默认情况下,该属性将创建一个对象来存储对象属性中的附加信息,例如会话标识符和原始IP地址。 如果可以从预身份验证机制获取用户角色信息,则数据也存储在此属性中,详细信息实现接口。 这使身份验证提供程序能够读取外部分配给用户的权限。 接下来,我们将看一个具体的例子。authenticationDetailsSourceWebAuthenticationDetailsdetailsAuthenticationGrantedAuthoritiesContainerSpring中文文档

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

如果筛选器配置了作为此类实例的实例,则通过为一组预先确定的“可映射角色”中的每一个调用该方法来获取颁发机构信息。 该类从配置的 . 可能的实现包括在应用程序上下文中对列表进行硬编码,以及从文件中的信息中读取角色信息。 预身份验证示例应用程序使用后一种方法。authenticationDetailsSourceisUserInRole(String role)MappableAttributesRetriever<security-role>web.xmlSpring中文文档

还有一个附加阶段,其中角色(或属性)使用配置的 . 默认值只会将通常的前缀添加到名称中,但它可以让您完全控制行为。GrantedAuthorityAttributes2GrantedAuthoritiesMapperROLE_Spring中文文档

PreAuthenticatedAuthenticationProvider

预身份验证提供程序除了为用户加载对象外,几乎没有其他操作。 它通过委托给 . 后者与标准类似,但采用对象而不仅仅是用户名:UserDetailsAuthenticationUserDetailsServiceUserDetailsServiceAuthenticationSpring中文文档

public interface AuthenticationUserDetailsService {
	UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

这个接口可能还有其他用途,但通过预身份验证,它允许访问打包在对象中的权限,正如我们在上一节中看到的那样。 该类执行此操作。 或者,它可以通过实现委托给标准。AuthenticationPreAuthenticatedGrantedAuthoritiesUserDetailsServiceUserDetailsServiceUserDetailsByNameServiceWrapperSpring中文文档

Http403ForbiddenEntryPoint

AuthenticationEntryPoint 负责启动未经身份验证的用户的身份验证过程(当他们尝试访问受保护的资源时),但在预身份验证的情况下,这不适用。 仅当未将预身份验证与其他身份验证机制结合使用时,才可以使用此类的实例进行配置。 如果用户被拒绝,则将调用它,从而导致 null 身份验证。 如果调用,它始终返回 -forbidden 响应代码。ExceptionTranslationFilterAbstractPreAuthenticatedProcessingFilter403Spring中文文档

具体实施

X.509 身份验证在其单独的章节中进行了介绍。 在这里,我们将介绍一些为其他预身份验证方案提供支持的类。Spring中文文档

请求标头身份验证 (Siteminder)

外部身份验证系统可以通过在 HTTP 请求上设置特定标头来向应用程序提供信息。 一个众所周知的例子是 Siteminder,它在名为 . 这种机制由类支持,该类只是从标头中提取用户名。 默认使用名称作为标头名称。 有关更多详细信息,请参阅 Javadoc。SM_USERRequestHeaderAuthenticationFilterSM_USERSpring中文文档

请注意,当使用这样的系统时,框架根本不执行身份验证检查,正确配置外部系统并保护对应用程序的所有访问非常重要。 如果攻击者能够在不检测到的情况下伪造其原始请求中的标头,那么他们可能会选择他们想要的任何用户名。Spring中文文档

Siteminder 配置示例

使用此筛选器的典型配置如下所示:Spring中文文档

<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>

<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
	<bean id="userDetailsServiceWrapper"
		class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<property name="userDetailsService" ref="userDetailsService"/>
	</bean>
</property>
</bean>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

我们在这里假设安全命名空间用于配置。 还假定您已将一个(称为“userDetailsService”)添加到配置中以加载用户的角色。UserDetailsServiceSpring中文文档

Java EE 容器认证

该类将从 的属性中提取用户名。 此过滤器的使用通常与 Java EE 角色的使用结合使用,如上文 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 中所述。J2eePreAuthenticatedProcessingFilteruserPrincipalHttpServletRequestSpring中文文档

示例项目中有一个使用此方法的示例应用程序,因此,请从 GitHub 获取代码,并查看应用程序上下文文件(如果有兴趣)。Spring中文文档

请注意,当使用这样的系统时,框架根本不执行身份验证检查,正确配置外部系统并保护对应用程序的所有访问非常重要。 如果攻击者能够在不检测到的情况下伪造其原始请求中的标头,那么他们可能会选择他们想要的任何用户名。Spring中文文档