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

Spring OAuth2资源服务器禁用SSL验证后仍出现SSL握手错误如何解决

问题原因

你当前的SSL禁用代码仅关闭了证书链信任校验,没有关闭HTTPS的主机名校验:HTTPS校验分为两个环节,第一步校验证书是否被信任,第二步校验访问的域名/IP和证书中配置的SAN(主体可选名称)或CN(通用名)匹配。你禁用第一步后解决了PKIX路径错误,但触发了第二步的主机名不匹配报错。


完整解决方案(仅适用于开发测试环境,生产环境严禁使用)

1. 修改SSL工具类,补充主机名校验禁用

import javax.net.ssl.*;
import java.security.cert.X509Certificate;

public final class SSLUtil {

    private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }
    };

    // 新增全放行主机名验证器
    private static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = (hostname, session) -> true;

    public static void turnOffSslChecking() throws Exception {
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, UNQUESTIONING_TRUST_MANAGER, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        // 配置默认主机名验证器
        HttpsURLConnection.setDefaultHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER);
    }

    public static void turnOnSslChecking() throws Exception {
        SSLContext.getInstance("SSL").init(null, null, null);
        HttpsURLConnection.setDefaultHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier());
    }

    private SSLUtil() {
        throw new UnsupportedOperationException("Do not instantiate libraries.");
    }
}

2. 自定义JwtDecoder,使用配置了无SSL校验的RestTemplate拉取OIDC配置

Spring Security 默认的JwtDecoders.fromIssuerLocation内部使用的RestTemplate可能不会继承你配置的JDK全局SSL设置,更稳妥的方式是手动构造RestTemplate并传入配置:

import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.net.HttpURLConnection;

@Configuration
public class JwtConfig {

    @Bean
    JwtDecoder jwtDecoderByIssuerUri(final OAuth2ResourceServerProperties properties) throws Exception {
        SSLUtil.turnOffSslChecking();
        
        // 构造自定义RestTemplate,使用我们配置的无校验SSL上下文
        RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory() {
            @Override
            protected void prepareConnection(HttpURLConnection connection, String httpMethod) {
                if (connection instanceof HttpsURLConnection httpsConn) {
                    httpsConn.setHostnameVerifier((hostname, session) -> true);
                    // 直接指定无校验SocketFactory,避免依赖全局配置
                    httpsConn.setSSLSocketFactory(SSLContext.getInstance("SSL").getSocketFactory());
                }
            }
        });
        
        // 用自定义RestTemplate拉取OIDC配置并构造JwtDecoder
        return JwtDecoders.fromIssuerLocation(properties.getJwt().getIssuerUri())
                .restOperations(restTemplate);
    }
}

生产环境正确做法

不要禁用SSL校验,而是将授权服务器的根证书导入到JDK的信任库中,同时保证证书的SAN字段包含你访问授权服务器使用的域名/IP,从根源解决问题。


内容的提问来源于stack exchange,提问作者Mulgard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:57:00