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

Java客户端如何查看PKIX证书链验证失败的服务器证书?

解决Netty SSL握手失败后无法查看服务器证书的问题

方法1:自定义信任管理器捕获验证失败时的证书链

Netty默认信任管理器在验证失败时会直接抛出异常,不会保留证书信息。你可以实现自定义X509TrustManager,在验证失败的分支里先保存或打印服务器传来的证书链,再抛出异常维持原有逻辑。

示例代码:

public class DebugTrustManager implements X509TrustManager {
    private final X509TrustManager delegate;

    public DebugTrustManager(X509TrustManager delegate) {
        this.delegate = delegate;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        delegate.checkClientTrusted(chain, authType);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        try {
            delegate.checkServerTrusted(chain, authType);
        } catch (CertificateException e) {
            // 打印或保存服务器证书链
            System.out.println("验证失败的服务器证书链:");
            for (X509Certificate cert : chain) {
                System.out.println("证书主题:" + cert.getSubjectDN());
                System.out.println("证书颁发者:" + cert.getIssuerDN());
                System.out.println("有效期至:" + cert.getNotAfter());
            }
            throw e;
        }
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return delegate.getAcceptedIssuers();
    }
}

构建SslContext时替换默认信任管理器:

// 加载原有信任库
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("your-truststore.jks"), "password".toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);

// 提取默认X509TrustManager
X509TrustManager originalTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        originalTm = (X509TrustManager) tm;
        break;
    }
}

DebugTrustManager debugTm = new DebugTrustManager(originalTm);

// 构建自定义SslContext
SslContext sslContext = SslContextBuilder.forClient()
        .trustManager(debugTm)
        // 保留原有其他配置
        .build();

方法2:开启JVM SSL调试日志

通过JVM启动参数开启SSL调试日志,无需修改代码就能获取服务器证书链的详细信息:

-Djavax.net.debug=ssl:handshake:cert

启动客户端后,日志会输出服务器传递的证书链内容,包括证书主题、颁发者、序列号等关键信息。如果需要更全面的握手细节,可以用:

-Djavax.net.debug=ssl:handshake:verbose

方法3:临时禁用证书验证(仅调试用)

如果只是临时调试,可以关闭证书验证让握手成功,之后通过SSLSession.getPeerCertificates()获取证书。注意:此方法绝对不能用于生产环境。

构建SslContext时配置:

SslContext sslContext = SslContextBuilder.forClient()
        .trustManager(InsecureTrustManagerFactory.INSTANCE)
        // 保留原有其他配置
        .build();

握手成功后在事件中获取证书:

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof SslHandshakeCompletionEvent) {
        SslHandshakeCompletionEvent event = (SslHandshakeCompletionEvent) evt;
        if (event.isSuccess()) {
            SSLSession session = ctx.channel().attr(SslHandler.SSL_SESSION).get();
            X509Certificate[] peerCerts = (X509Certificate[]) session.getPeerCertificates();
            // 处理证书信息
        }
    }
    super.userEventTriggered(ctx, evt);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 18:52:18