You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:55:27