实现预认证
1. 前言
上一节我们讨论了如何保存用户登录状态,本节我们讨论另一个问题,如果无法在 Spring Security 中实现认证,又希望使用 Spring Security 做后续的安全处理该如何实现?
我们知道,Spring Security 既包含认证的标准,也包含鉴权的标准,而鉴权又是认证后续步骤。那如果我们希望 Spring Security 帮我们处理权限,而又希望跳过认证步骤(比如已在外部系统实现认证),这是该如何配置?我们就需要使用「预先认证」解决方案了。
本节,我们重点讨论如何用 Spring Security 实现预先认证效果。
2. 预先认证概述
预先认证的使用场景如:已使用x.509 认证、J2EE 容器等方式通过认证。预认证有两个主要步骤:
- 识别发起请求的用户身份;
- 为该用户返回权限。
具体的运行机制与外部认证环境有关。当使用 x.509 证书认证时,用户的识别信息从证书中获取并添加在 Http 请求头中。如果是 J2EE 容器认证,用户的身份信息通过 Http 请求对象的 getUserPrincipal()
方法获得。有时,外部认证系统可以提供用户的身份信息、权限信息,但有时,权限信息要从其他数据源中获取,例如通过 UserDetailsService
。
3. Spring Security 集成方法
3.1 框架层说明
由于大部分的预先认证模式比较一致,Spring Security 为此提供了一个框架,用来实现预先认证的身份提供器。预先认证模块的实现类均在包 org.springframework.security.web.authentication.preauth
之下。
此处介绍几个核心的成员对象。
3.1.1 AbstractPreAuthenticatedProcessingFilter
该类用来检查当前安全上下文的有效性,如果内容为空,它会尝试从 Http 请求中解析出用户信息,并将其提交到认证管理器 AuthenticationManager
。使用该基类需要实现如下两个方法:
- 获取认证身份信息
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
- 获取认证凭证
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
通过对这两个方法的调用,该过滤器将创建一个票据对象实例 PreAuthenticatedAuthenticationToken
,该实例包含用户认证结果,并用于认证过程。但是此处的认证过程,仅仅是用来获取权限,只是为了满足标准 Spring Security 流程而实施的步骤。
和其他的安全过滤器类似,预先认证的过滤器包含一个 authenticationDetailsSource
属性,用于保存预先认证流程中的相关数据。
3.1.2 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
如果前述过滤器配置了 authenticationDetailsSource
,其权限信息可以通过 isUserInRole(String role)
方法判断,角色信息的配置通过 MappableAttributesRetriever
获取,或者通过 <security-role>
标签配置到 web.xml
文件中。
3.1.3 PreAuthenticatedAuthenticationProvider
预先认证身份提供者中的 UserDetails
对象与其他的身份提供者逻辑略有不同,主要体现在获取 Authentication
认证信息时,仅需用户名参数即可。
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
3.1.4 Http403ForbiddenEntryPoint
对 AuthenticationEntryPoint 的配置用对未认证用户来发起认证流程。在预先认证流程中,该配置不起作用,我们只需要配置 ExceptionTranslationFilter
用于处理安全过滤器无法获得用户信息的情形,通常在这种情况下,请求端将收到 403 错误。
3.2 具体实现说明
关于 x.509 认证的集成实现,我们在后续文章中具体说明。
针对 J2EE 容器认证的集成实现,需要指定其 authenticationDetailsSource
对象为 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
实例。
4. 小结
本节我们讨论了如何在 Spring Security 中跳过认证过程,使用外部认证结果,本节主要知识点有:
- 预认证是指认证过程被安排在其他程序中完成的认证方式;
- 预认证是一类认证方式的统称,最常见的预认证方式是 X.509 证书认证;
- Spring Security 集成预认证相当于让认证过程什么都不执行,只保留鉴别权限的功能。
下节我们讨论如何使用 X.509 证书方式认证。