SpringSeurity中文文档(Servlet Pre-Authentication Scenarios)

Pre-Authentication Scenarios

示例包括 X.509、Siteminder 以及 Java EE 容器中的身份验证,应用程序在这些环境中运行。当使用预身份验证时,Spring Security 必须执行以下操作:

  • 识别发出请求的用户。
  • 为用户获取权限。

具体的细节取决于外部认证机制。在 X.509 的情况下,用户可能通过他们的证书信息来识别,或者在 Siteminder 的情况下,通过 HTTP 请求头识别。如果依赖容器认证,用户是通过调用传入 HTTP 请求的 getUserPrincipal() 方法来识别的。在某些情况下,外部机制可能为用户提供角色和权限信息。然而,在其他情况下,您必须从单独的来源获取权限,例如 UserDetailsService。

Pre-Authentication Framework Classes

由于大多数预认证机制遵循相同的模式,Spring Security 有一组类,用于实现预认证身份验证提供程序的内部框架。这消除了重复,并允许以结构化的方式添加新的实现,而无需从头开始编写所有内容。如果您想使用像 X.509 认证这样的东西,您不需要知道这些类,因为它已经有了一个更简单、更易于使用的命名空间配置选项。如果您需要使用显式 bean 配置,或者计划编写自己的实现,您需要了解提供的实现是如何工作的。您可以在 org.springframework.security.web.authentication.preauth 下找到这些类。我们在这里只提供一个大纲,因此您应该适当地查阅 Javadoc 和源代码。

AbstractPreAuthenticatedProcessingFilter

这个类检查安全上下文当前的内容,如果为空,则尝试从 HTTP 请求中提取用户信息并将其提交给 AuthenticationManager。子类重写以下方法以获取这些信息。

Override AbstractPreAuthenticatedProcessingFilter

java 复制代码
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);

protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);

调用这些方法后,过滤器将创建一个包含返回数据的 PreAuthenticatedAuthenticationToken 并提交进行身份验证。在这里,"身份验证"实际上只是指进一步的 processing,可能会加载用户的权限,但是遵循标准的 Spring Security 身份验证架构。

与其他 Spring Security 身份验证过滤器一样,预身份验证过滤器有一个 authenticationDetailsSource 属性,默认情况下,它创建一个 WebAuthenticationDetails 对象来存储额外的信息,比如会话标识符和原始 IP 地址,这些信息存储在 Authentication 对象的 details 属性中。在可以从预身份验证机制获取用户角色信息的情况下,数据也会存储在这个属性中,详细信息实现了 GrantedAuthoritiesContainer 接口。这使得身份验证提供者能够读取外部分配给用户的权限。我们接下来看一个具体的例子。

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

如果过滤器配置了 authenticationDetailsSource,且是本类的一个实例,权限信息将通过为每个预定义的"可映射角色"集合调用 isUserInRole(String role) 方法来获取。该类从配置的 MappableAttributesRetriever 获取这些信息。可能的实现包括在应用程序上下文中硬编码一个列表,以及从 web.xml 文件中的 信息读取角色信息。预身份验证示例应用程序使用了后一种方法。

还有一个额外的阶段,其中使用配置的 Attributes2GrantedAuthoritiesMapper 将角色(或属性)映射到 Spring Security GrantedAuthority 对象。默认情况下,它只是在名称前加上通常的 ROLE_ 前缀,但这为您提供了完全控制行为的能力。

PreAuthenticatedAuthenticationProvider

预认证提供者除了为用户加载 UserDetails 对象外,几乎没有更多的事情要做。它通过委托给一个 AuthenticationUserDetailsService 来完成这项工作。后者与标准的 UserDetailsService 类似,但它接受一个 Authentication 对象而不仅仅是用户名:

java 复制代码
public interface AuthenticationUserDetailsService {
	UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

这个接口可能还有其他用途,但是,在预认证中,它允许访问封装在 Authentication 对象中的权限,正如我们在上一节中看到的。PreAuthenticatedGrantedAuthoritiesUserDetailsService 类就是这样做的。或者,它可以通过 UserDetailsByNameServiceWrapper 实现委派给一个标准的 UserDetailsService。

Http403ForbiddenEntryPoint

AuthenticationEntryPoint 负责为未经认证的用户启动认证过程(当他们尝试访问受保护的资源时)。然而,在预认证的情况下,这并不适用。只有当您不将预认证与其他认证机制结合使用时,您才需要配置 ExceptionTranslationFilter 与此类的一个实例。如果用户被 AbstractPreAuthenticatedProcessingFilter 拒绝,导致认证为 null,则会调用它。如果被调用,它总是返回一个 403-禁止的响应码。

Concrete Implementations

X.509 认证在其自己的章节中有所涉及。在这里,我们查看一些为其他预认证场景提供支持的类。

Request-Header Authentication (Siteminder)

外部认证系统可能通过在 HTTP 请求上设置特定头部来向应用程序提供信息。这种机制的著名示例是 Siteminder,它通过一个名为 SM_USER 的头部传递用户名。这种机制由 RequestHeaderAuthenticationFilter 类支持,它只从头部提取用户名。默认情况下,它使用 SM_USER 作为头部名称。请参阅 Javadoc 以获取更多详细信息。

Siteminder Example Configuration

下面的示例演示使用此筛选器的典型配置:

java 复制代码
<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(名为 "userDetailsService"),以加载用户的角色。

Java EE Container Authentication

J2eePreAuthenticatedProcessingFilter 类从 HttpServletRequest 的 userPrincipal 属性中提取用户名。使用这个过滤器通常需要结合使用 Java EE 角色,正如前面在 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 中所描述的。

在代码库中有一个使用这种方法的示例应用程序,因此如果您感兴趣,可以从 Github 获取代码并查看应用程序上下文文件。

相关推荐
yaoxin5211238 分钟前
131. Java 泛型 - 目标类型与泛型推断
java
甜鲸鱼20 分钟前
在Maven多模块项目中进行跨模块的SpringBoot单元测试
spring boot·单元测试·maven
惊骇世俗王某人24 分钟前
1. 深入理解ArrayList源码
java·开发语言
用户403159863966333 分钟前
表达式并发计算
java·算法
SimonKing1 小时前
告别System.currentTimeMillis()!Java高精度计时最佳实践
java·后端·程序员
Dcs1 小时前
JUnit 5架构如何用模块化颠覆测试框架?
java
chanalbert1 小时前
Nacos 技术研究文档(基于 Nacos 3)
spring boot·分布式·spring cloud
肉肉不想干后端1 小时前
gRPC服务架构整合springboot部署实践指南
java
chanalbert1 小时前
Spring Cloud分布式配置中心:架构设计与技术实践
spring boot·spring·spring cloud
天天摸鱼的java工程师1 小时前
volatile关键字实战指南:八年Java开发者详解五大应用场景
java·后端