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 获取代码并查看应用程序上下文文件。

相关推荐
你是狒狒吗2 分钟前
TM中,return new TransactionManagerImpl(raf, fc);为什么返回是new了一个新的实例
java·开发语言·数据库
鳄鱼杆7 分钟前
服务器 | Centos 9 系统中,如何部署SpringBoot后端项目?
服务器·spring boot·centos
勤奋的知更鸟14 分钟前
Java编程之组合模式
java·开发语言·设计模式·组合模式
千|寻14 分钟前
【画江湖】langchain4j - Java1.8下spring boot集成ollama调用本地大模型之问道系列(第一问)
java·spring boot·后端·langchain
爱编程的喵28 分钟前
深入理解JavaScript原型机制:从Java到JS的面向对象编程之路
java·前端·javascript
on the way 12339 分钟前
行为型设计模式之Mediator(中介者)
java·设计模式·中介者模式
保持学习ing41 分钟前
Spring注解开发
java·深度学习·spring·框架
techzhi42 分钟前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
酷爱码1 小时前
Spring Boot 整合 Apache Flink 的详细过程
spring boot·flink·apache
异常君1 小时前
Spring 中的 FactoryBean 与 BeanFactory:核心概念深度解析
java·spring·面试