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

如何通过Java建立SSH连接访问PostgreSQL?求助隧道搭建及报错解决

使用Java+JDBC连接PostgreSQL并通过SSH隧道访问

我来帮你一步步解决这个问题~首先先搞定你遇到的pg_hba.conf报错,再给你讲两种SSH隧道的实现方式,你可以根据自己的场景选择。

先解决pg_hba.conf报错问题

你碰到的这个错误:

org.postgresql.util.PSQLException: FATAL: no pg_hba.conf entry for a host

本质是PostgreSQL的安全配置文件pg_hba.conf没允许你的连接源(大概率是SSH隧道映射的本地IP,比如127.0.0.1)访问数据库。你需要登录到PostgreSQL服务器上修改这个文件:

  • 打开pg_hba.conf(通常在PostgreSQL的data目录下),添加一条规则:
    host    all             all             127.0.0.1/32            scram-sha-256
    
    这条规则允许本地127.0.0.1的所有用户访问所有数据库,认证方式用scram-sha-256(如果你的PostgreSQL版本较旧,可能用md5,根据实际情况调整)。
  • 保存文件后,重启PostgreSQL服务,让配置生效。

关于是否需要写Java程序创建SSH隧道?

答案是两种方式都可行,看你的需求场景:

方式1:用外部工具先建隧道(不用改Java代码,适合快速测试)

这种方式最简单,不用写额外的Java代码,先通过命令行工具(比如OpenSSH)建立SSH隧道,再用普通的JDBC代码连接本地映射的端口就行。

操作步骤:

  1. 打开终端,执行这条命令(替换成你的实际信息):
    ssh -L 5432:localhost:5432 你的SSH用户名@SSH服务器IP
    
    解释:把你本地的5432端口,转发到SSH服务器上的localhost:5432(也就是PostgreSQL的默认端口)。执行后输入SSH密码,保持终端窗口打开,隧道就建立好了。
  2. 然后写普通的JDBC连接代码,连接本地的5432端口:
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class PostgresConn {
        public static void main(String[] args) {
            String url = "jdbc:postgresql://localhost:5432/你的数据库名";
            String user = "PostgreSQL用户名";
            String password = "PostgreSQL密码";
    
            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                System.out.println("成功连到PostgreSQL啦!");
            } catch (SQLException e) {
                System.out.println("连接失败...");
                e.printStackTrace();
            }
        }
    }
    

方式2:在Java代码里集成SSH隧道(适合生产环境,不用依赖外部工具)

如果要把SSH隧道集成到你的Java应用里,不用每次手动开终端,那可以用JSch这个Java的SSH库来实现。

操作步骤:

  1. 先给项目添加JSch依赖(比如用Maven的话,在pom.xml里加):
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.55</version>
    </dependency>
    
  2. 然后编写代码,先建立SSH隧道,再连接JDBC:
    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.Session;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    
    public class PostgresWithSSH {
        public static void main(String[] args) {
            // SSH服务器信息
            String sshHost = "你的SSH服务器IP";
            String sshUser = "SSH用户名";
            String sshPassword = "SSH密码";
            int sshPort = 22; // 默认SSH端口
    
            // PostgreSQL服务器信息(注意:是相对于SSH服务器的地址,同机器则填localhost)
            String pgHost = "localhost";
            int pgPort = 5432;
            String pgDbName = "你的数据库名";
            String pgUser = "PostgreSQL用户名";
            String pgPassword = "PostgreSQL密码";
    
            // 本地映射端口(选一个未被占用的,比如5433)
            int localPort = 5433;
    
            Session sshSession = null;
            Connection pgConn = null;
    
            try {
                // 建立SSH会话
                JSch jsch = new JSch();
                sshSession = jsch.getSession(sshUser, sshHost, sshPort);
                sshSession.setPassword(sshPassword);
    
                // 跳过主机密钥检查(生产环境别这么做!应提前添加SSH服务器公钥到信任列表)
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(config);
    
                sshSession.connect();
                System.out.println("SSH隧道连接成功!");
    
                // 设置端口转发:本地端口 -> SSH服务器 -> PostgreSQL服务器
                sshSession.setPortForwardingL(localPort, pgHost, pgPort);
    
                // 连接PostgreSQL,使用本地映射端口
                String jdbcUrl = String.format("jdbc:postgresql://localhost:%d/%s", localPort, pgDbName);
                pgConn = DriverManager.getConnection(jdbcUrl, pgUser, pgPassword);
                System.out.println("成功连到PostgreSQL数据库!");
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 用完关闭连接
                try {
                    if (pgConn != null) pgConn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                if (sshSession != null && sshSession.isConnected()) {
                    sshSession.disconnect();
                    System.out.println("SSH隧道已关闭");
                }
            }
        }
    }
    

一些注意事项

  • 生产环境不要使用StrictHostKeyChecking=no,应该提前把SSH服务器的公钥添加到本地known_hosts文件中,避免中间人攻击。
  • 确保SSH服务器的22端口、PostgreSQL的5432端口都已开放,且网络连通正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:48:58