如何配置Spring Security为OAuth2令牌自省请求启用mTLS?
配置Spring Security OAuth2资源服务器的mTLS令牌自省
要让令牌自省请求通过mTLS认证,核心是给NimbusOpaqueTokenIntrospector的底层HTTP请求配置客户端证书。下面分步骤实现:
1. 配置SSL上下文(加载客户端证书)
首先创建SSLContext,加载客户端证书的密钥库(包含客户端证书和私钥)以及信任库(用于信任自省服务器的证书)。假设你已有客户端密钥库(如client-keystore.p12)和信任库(如truststore.p12),并知晓对应密码:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import javax.net.ssl.SSLContext; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import java.io.FileInputStream; import java.security.KeyStore; @Component @ConfigurationProperties(prefix = "ssl") public class SslProperties { private String keystorePath; private String keystorePassword; private String truststorePath; private String truststorePassword; // 生成getter和setter public String getKeystorePath() { return keystorePath; } public void setKeystorePath(String keystorePath) { this.keystorePath = keystorePath; } public String getKeystorePassword() { return keystorePassword; } public void setKeystorePassword(String keystorePassword) { this.keystorePassword = keystorePassword; } public String getTruststorePath() { return truststorePath; } public void setTruststorePath(String truststorePath) { this.truststorePath = truststorePath; } public String getTruststorePassword() { return truststorePassword; } public void setTruststorePassword(String truststorePassword) { this.truststorePassword = truststorePassword; } } @Configuration public class SslConfig { @Bean public SSLContext sslContext(SslProperties sslProps) throws Exception { // 加载客户端密钥库 KeyStore keyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream keyStoreStream = new FileInputStream(sslProps.getKeystorePath())) { keyStore.load(keyStoreStream, sslProps.getKeystorePassword().toCharArray()); } // 加载信任库 KeyStore trustStore = KeyStore.getInstance("PKCS12"); try (FileInputStream trustStoreStream = new FileInputStream(sslProps.getTruststorePath())) { trustStore.load(trustStoreStream, sslProps.getTruststorePassword().toCharArray()); } // 初始化密钥管理器和信任管理器 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, sslProps.getKeystorePassword().toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); // 创建SSLContext SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; } }
2. 配置带SSL的RestTemplate
基于上面的SSLContext,创建支持mTLS的RestTemplate:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import javax.net.ssl.SSLContext; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @Configuration public class RestTemplateConfig { @Bean public RestTemplate mtlsRestTemplate(SSLContext sslContext) { // 创建支持mTLS的HttpClient CloseableHttpClient httpClient = HttpClients.custom() .setSSLContext(sslContext) .build(); // 设置请求工厂 HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); return new RestTemplate(requestFactory); } }
3. 配置自定义的NimbusOpaqueTokenIntrospector
将带mTLS的RestTemplate注入到NimbusOpaqueTokenIntrospector,替换默认HTTP客户端:
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector; import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; import org.springframework.web.client.RestOperations; @Configuration public class OpaqueTokenConfig { @Bean public OpaqueTokenIntrospector myIntrospector(RestOperations mtlsRestTemplate) { // 替换为你的令牌自省服务器地址 String introspectionUri = "https://your-introspection-server.com/oauth2/introspect"; // 替换为资源服务器的客户端ID(自省服务器要求时填写) String clientId = "your-resource-server-client-id"; // 替换为资源服务器的客户端密钥(自省服务器要求时填写) String clientSecret = "your-resource-server-client-secret"; // 创建带mTLS支持的自省器 NimbusOpaqueTokenIntrospector introspector = new NimbusOpaqueTokenIntrospector( introspectionUri, clientId, clientSecret, mtlsRestTemplate); return introspector; } }
4. 保持原有SecurityFilterChain配置
你的原有安全配置无需修改,myIntrospector() Bean会自动注入带mTLS支持的自省器:
@Configuration @EnableWebSecurity public class MyCustomSecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .opaqueToken(opaqueToken -> opaqueToken .introspector(myIntrospector()) ) ); return http.build(); } }
5. 配置文件(application.yml)
添加SSL相关配置项:
ssl: keystore-path: classpath:client-keystore.p12 keystore-password: your-keystore-password truststore-path: classpath:truststore.p12 truststore-password: your-truststore-password
关键说明
- 若自省服务器证书由公共CA签发,信任库可直接使用JDK默认的
cacerts,无需自定义。 - 若自省服务器不需要客户端ID和密钥,可使用
NimbusOpaqueTokenIntrospector的无clientId/clientSecret构造方法。 - 密钥库格式若为JKS,需将
KeyStore.getInstance()的参数改为"JKS"。
内容的提问来源于stack exchange,提问作者eztam
相关产品推荐
相关产品推荐

