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

连接AWS EC2上MongoDB遇SocketTimeoutException,求Java配置PEM及用户名方法

解决AWS EC2上MongoDB Java连接超时及PEM认证配置问题

嘿,遇到MongoDB连接超时和Java里不知道怎么配置PEM证书、用户名认证的问题是吧?我帮你一步步捋清楚解决方案~

一、先搞定「java.net.SocketTimeoutException: connect timed out」超时问题

你能用Putty连EC2,说明EC2本身网络是通的,但MongoDB连不上,大概率是这几个环节出了问题:

  • EC2安全组没开放27017端口:Putty用的是22端口,和MongoDB的27017完全不搭。赶紧去AWS控制台的EC2安全组里,添加入站规则——允许你Java客户端所在的IP(测试阶段可以临时用0.0.0.0/0,但生产环境绝对别这么干)访问27017端口(TCP协议)。
  • MongoDB绑定地址限制了外部访问:打开EC2上的MongoDB配置文件(一般是/etc/mongod.conf),找到net.bindIp配置项,默认可能是127.0.0.1,这会导致只有EC2本地能访问MongoDB。改成0.0.0.0(允许所有IP访问)或者EC2的私有IP,然后重启MongoDB服务:sudo systemctl restart mongod。
  • EC2本地防火墙拦截了27017端口:如果EC2上开了iptables或者ufw这类防火墙,得确保27017端口被放行。比如用iptables的话,执行sudo iptables -A INPUT -p tcp --dport 27017 -j ACCEPT,然后保存规则。

二、Java代码里配置PEM证书及用户名认证

你原来的代码只是简单的裸连接,没配置SSL和认证信息,肯定没法通过MongoDB的安全校验。下面分两种常见情况给你代码示例:

情况1:MongoDB直接开放27017端口并启用SSL认证

如果你的MongoDB已经配置了SSL(用PEM证书做身份验证),那Java代码需要加载PEM证书并配置SSL上下文,同时带上用户名密码:

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.DB;
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 MongoDbSslConnection {
    public static void main(String[] args) {
        try {
            // 1. 加载你的PEM证书文件
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            FileInputStream pemInputStream = new FileInputStream("/绝对路径/your-mongo-cert.pem");
            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(pemInputStream);

            // 2. 创建临时密钥库并添加证书
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            keyStore.setCertificateEntry("mongo-trust-cert", cert);

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

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

            // 5. 配置MongoDB客户端的SSL选项
            MongoClientOptions clientOptions = MongoClientOptions.builder()
                    .sslEnabled(true)
                    .sslContext(sslContext)
                    .build();

            // 6. 设置MongoDB认证信息(用户名、认证数据库、密码)
            MongoCredential credential = MongoCredential.createCredential(
                    "你的MongoDB用户名",
                    "userDB",  // 和你要连接的数据库一致
                    "你的密码".toCharArray()
            );

            // 7. 建立连接
            ServerAddress serverAddr = new ServerAddress("ec2-xx-xx-xxx-xx.xx-xxxx-1.xxxxxx.amazonaws.com", 27017);
            MongoClient mongoClient = new MongoClient(serverAddr, Arrays.asList(credential), clientOptions);

            // 测试连接
            DB db = mongoClient.getDB("userDB");
            System.out.println("成功连接到数据库:" + db.getName());

            // 记得用完关闭连接
            mongoClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

情况2:通过SSH隧道访问MongoDB(更安全,适合生产环境)

如果你的MongoDB还是绑定127.0.0.1(只允许EC2本地访问),你用Putty是通过SSH隧道转发端口来访问的,那Java里也需要先建立SSH隧道,再连接本地转发的端口:

首先要引入JSch库(用来实现SSH隧道),然后代码如下:

import com.mongodb.MongoClient;
import com.mongodb.DB;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.util.Properties;

public class MongoDbSshTunnelConnection {
    public static void main(String[] args) {
        Session sshSession = null;
        MongoClient mongoClient = null;
        try {
            // 1. 配置SSH连接信息
            JSch jsch = new JSch();
            // 加载你的EC2 PEM密钥文件
            jsch.addIdentity("/绝对路径/your-ec2-key.pem");
            // SSH用户名一般是ec2-user(Amazon Linux)或者ubuntu(Ubuntu系统)
            sshSession = jsch.getSession("ec2-user", "ec2-xx-xx-xxx-xx.xx-xxxx-1.xxxxxx.amazonaws.com", 22);
            
            // 跳过主机密钥校验(测试用,生产环境建议配置正确的校验)
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(config);
            
            // 建立SSH连接
            sshSession.connect();
            
            // 2. 端口转发:本地27017端口转发到EC2的127.0.0.1:27017
            int localPort = 27017;
            String remoteHost = "127.0.0.1";
            int remotePort = 27017;
            sshSession.setPortForwardingL(localPort, remoteHost, remotePort);
            
            // 3. 连接MongoDB(此时连本地的27017端口即可)
            mongoClient = new MongoClient("localhost", localPort);
            DB db = mongoClient.getDB("userDB");
            System.out.println("成功通过SSH隧道连接到数据库:" + db.getName());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (mongoClient != null) {
                mongoClient.close();
            }
            if (sshSession != null && sshSession.isConnected()) {
                sshSession.disconnect();
            }
        }
    }
}

最后提醒

  • 生产环境别用0.0.0.0/0开放27017端口,一定要限制为固定的客户端IP。
  • 如果用SSH隧道,记得给JSch库添加依赖(比如Maven里加com.jcraft:jsch:0.1.55)。
  • 确认MongoDB已经开启了认证(在mongod.conf里设置security.authorization: enabled),不然用户名密码配置了也没用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:03:58