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

Spring Boot使用RS256验证JWT时遇SSL握手异常求助

问题解决思路

异常本质

javax.net.ssl.SSLHandshakeException 核心原因是JVM默认信任库(cacerts)未包含JWKS服务器SSL证书的根CA证书,无法完成证书链有效性验证,导致HTTPS请求失败。

解决方案

方案1:直接从JWKS的x5c字段构建公钥(推荐)

既然提供方确认JWKS返回的信息包含完整验证所需内容,可跳过HTTPS请求,直接解析返回的x5c字段(Base64编码的证书链)生成公钥,彻底绕开SSL问题:

import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.io.ByteArrayInputStream;
import java.util.Base64;

private RSAPublicKey loadPublicKeyFromX5c(String x5cValue) throws Exception {
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    // 移除Base64字符串中的换行符并解码
    byte[] certBytes = Base64.getDecoder().decode(x5cValue.replaceAll("\\s+", ""));
    X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
    return (RSAPublicKey) cert.getPublicKey();
}

使用时,可直接复用JWKS返回的x5c字段值;若需动态获取JWKS内容,可先通过信任该证书的HTTP客户端拉取数据后解析。

方案2:将JWKS服务器证书导入JVM信任库(生产环境标准做法)

  1. 下载服务器证书:
    • 浏览器访问https://xxxxx/oauth/nam/keys,点击地址栏锁图标导出证书(格式选DER或PEM);
    • 或用OpenSSL命令下载:
      openssl s_client -connect xxxxx:443 < /dev/null | openssl x509 -outform PEM > jwks-server-cert.pem
      
  2. 导入到JVM信任库:
    找到JVM安装目录下的信任库文件(JDK 8及以下路径为$JAVA_HOME/jre/lib/security/cacerts,JDK 9+为$JAVA_HOME/lib/security/cacerts),执行导入命令(默认密码为changeit):
    keytool -import -alias jwks-server -file jwks-server-cert.pem -keystore $JAVA_HOME/jre/lib/security/cacerts
    

方案3:代码中跳过SSL验证(仅临时测试用,禁止生产环境使用)

若仅用于临时调试,可在代码中强制信任所有证书,但会引入严重安全风险:

import javax.net.ssl.*;
import java.security.cert.X509Certificate;
import java.net.URL;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwk.JwkProvider;

private RSAPublicKey loadPublicKey(DecodedJWT token) throws Exception {
    final String url = "https://XXXXXXXX/oauth/nam/keys";
    
    // 创建信任所有证书的SSL上下文
    TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() { return null; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }
    };
    
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
    
    JwkProvider provider = new UrlJwkProvider(new URL(url));
    return (RSAPublicKey) provider.get(token.getKeyId()).getPublicKey();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:05:17