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

Windows环境下通过SSH隧道用Java连接DocumentDB遇SSL错误求助

DocumentDB Java连接SSL握手失败(PKIX路径问题)解决思路

核心问题分析

你遇到的PKIX路径构建失败+SSL握手超时,本质对应两个问题:JVM未信任DocumentDB的CA证书,且主机名验证不通过(因为SSH隧道映射到localhost,但证书绑定的是远程DocumentDB域名),和mongosh使用的--sslCAFile、--sslAllowInvalidHostnames参数直接相关。


具体解决步骤

1. 让JVM信任DocumentDB的CA证书

mongosh通过--sslCAFile指定了rds-ca.pem,Java需要把这个证书加入信任链,有两种实现方式:

方式一:导入到JVM系统信任库

用keytool命令将证书导入JRE默认信任库(Windows环境):

keytool -importcert -file rds-ca.pem -alias docdb-ca -keystore "%JAVA_HOME%\jre\lib\security\cacerts"
  • 提示输入密码时,默认密码为changeit
  • 确认导入时输入y即可完成操作
方式二:代码中自定义加载证书(无需修改系统信任库)

在Java代码中直接加载rds-ca.pem,构建自定义SSL上下文,示例代码片段:

// 加载CA证书文件
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (FileInputStream fis = new FileInputStream("rds-ca.pem")) {
    X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
    
    // 创建信任存储并添加证书
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(null);
    trustStore.setCertificateEntry("docdb-ca", cert);
    
    // 初始化信任管理器
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(trustStore);
    
    // 构建SSL上下文
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);
}

2. 关闭主机名验证(对应mongosh的--sslAllowInvalidHostnames)

因为你通过SSH隧道连接localhost:27017,但证书绑定的是远程DocumentDB域名my-cluster.eu-west-3.docdb.amazonaws.com,JVM默认会验证主机名匹配,必须关闭该验证:
在MongoClientSettings的SSL配置中添加:

.applyToSslSettings(builder -> {
    builder.enabled(true)
           .invalidHostNameAllowed(true); // 允许不匹配的主机名
})

3. 完整的MongoClient配置示例

整合上述配置,完整连接代码如下:

import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;

public class DocumentDBConnector {
    public static void main(String[] args) throws Exception {
        // 加载CA证书
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert;
        try (FileInputStream fis = new FileInputStream("rds-ca.pem")) {
            cert = (X509Certificate) cf.generateCertificate(fis);
        }

        // 构建信任存储
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null);
        trustStore.setCertificateEntry("docdb-ca", cert);

        // 初始化信任管理器
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);

        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        // 配置Mongo客户端
        MongoClientSettings settings = MongoClientSettings.builder()
                .applyToSslSettings(sslBuilder -> {
                    sslBuilder.enabled(true)
                              .invalidHostNameAllowed(true);
                })
                .sslContext(sslContext)
                .credential(MongoCredential.createCredential(
                        "user",  // 用户名
                        "admin", // 认证数据库(默认admin)
                        "pwd".toCharArray() // 密码
                ))
                .applyToClusterSettings(clusterBuilder ->
                        clusterBuilder.hosts(Arrays.asList(new ServerAddress("localhost", 27017)))
                )
                .build();

        // 建立连接并测试
        try (MongoClient client = MongoClients.create(settings)) {
            System.out.println("连接成功,数据库列表:");
            client.listDatabaseNames().forEach(System.out::println);
        }
    }
}

4. 排查网络及隧道状态

  • 确认SSH隧道持续运行:ssh -L 27017:my-cluster.eu-west-3.docdb.amazonaws.com:27017 ubuntu@my-ec2.com -N不能中断
  • 测试本地端口连通性:用telnet localhost 27017或Test-NetConnection localhost -Port 27017(PowerShell)验证端口是否开放
  • 检查Windows防火墙:确保Java程序未被阻止访问localhost:27017

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:45:33