跳到主要内容
版本:7.0.2

X.509 认证

DeepSeek V3 中英对照 X509 X.509 Authentication

X.509证书认证最常见的用途是在使用SSL时验证服务器的身份,尤其是在浏览器中使用HTTPS时最为普遍。浏览器会自动检查服务器提供的证书是否由其维护的可信证书颁发机构列表中的某个机构签发(即数字签名)。

您也可以使用带有“双向认证”的SSL。在这种情况下,服务器会在SSL握手过程中向客户端请求一个有效的证书。服务器通过检查客户端的证书是否由可接受的权威机构签名来验证客户端的身份。如果提供了有效的证书,应用程序可以通过Servlet API获取该证书。例如,如果您使用Tomcat,您应该阅读Tomcat SSL说明。在尝试与Spring Security集成之前,您应该先确保此功能正常工作。

Spring Security X.509 模块通过过滤器提取证书。它将证书映射到应用程序用户,并加载该用户被授予的权限集,以便与标准的 Spring Security 基础设施一起使用,特别是在使用 HttpSecurity DSL 时,至少会包含 FACTOR_X509 权限。

为您的Web应用程序添加X.509认证

响应式 X.509 认证类似,Servlet X.509 认证过滤器允许从客户端提供的证书中提取认证令牌。

以下示例展示了响应式 x509 安全配置:

@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
http
.x509(Customizer.withDefaults())
.authorizeHttpRequests((exchanges) -> exchanges
.anyRequest().authenticated()
);
return http.build();
}

在上述配置中,当未提供 principalExtractorauthenticationManager 时,将使用默认值。默认的主体提取器是 SubjectX500PrincipalExtractor,它从客户端提供的证书中提取 CN(通用名称)字段。默认的身份验证管理器是 ReactivePreAuthenticatedAuthenticationManager,它执行用户账户验证,检查由 principalExtractor 提取名称的用户账户是否存在,以及该账户是否未被锁定、禁用或过期。

以下示例展示了如何覆盖这些默认设置:

@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
SubjectX500PrincipalExtractor principalExtractor = new SubjectX500PrincipalExtractor();
principalExtractor.setExtractPrincipalNameFromEmail(true);

http
.x509((x509) -> x509
.x509PrincipalExtractor(principalExtractor)
)
.authorizeHttpRequests((exchanges) -> exchanges
.anyRequest().authenticated()
);
return http.build();
}

在前面的示例中,用户名是从客户端证书的 emailAddress 字段而非 CN 字段提取的,并且账户查找使用了自定义的 ReactiveAuthenticationManager 实例。

关于配置 Netty 和 WebClientcurl 命令行工具以使用双向 TLS 并启用 X.509 身份验证的示例,请参阅 github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/x509

在 Tomcat 中设置 SSL

Spring Security Samples 仓库 中提供了一些预生成的证书。如果你不想自己生成证书,可以使用这些证书来为测试启用 SSL。server.jks 文件包含了服务器证书、私钥以及颁发机构证书。此外,还有一些示例应用程序中用户的客户端证书文件。你可以将这些证书安装到浏览器中,以启用 SSL 客户端认证。

要运行支持SSL的Tomcat,请将server.jks文件放入Tomcat的conf目录,并在server.xml文件中添加以下连接器配置:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.home}/conf/server.jks"
keystoreType="JKS" keystorePass="password"
truststoreFile="${catalina.home}/conf/server.jks"
truststoreType="JKS" truststorePass="password"
/>

如果将 clientAuth 设置为 want,即使客户端不提供证书,SSL 连接仍可成功建立。但未提供证书的客户端将无法访问任何由 Spring Security 保护的对象,除非您使用非 X.509 认证机制,例如表单认证。