如何通过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目录下),添加一条规则:
这条规则允许本地127.0.0.1的所有用户访问所有数据库,认证方式用host all all 127.0.0.1/32 scram-sha-256scram-sha-256(如果你的PostgreSQL版本较旧,可能用md5,根据实际情况调整)。 - 保存文件后,重启PostgreSQL服务,让配置生效。
关于是否需要写Java程序创建SSH隧道?
答案是两种方式都可行,看你的需求场景:
方式1:用外部工具先建隧道(不用改Java代码,适合快速测试)
这种方式最简单,不用写额外的Java代码,先通过命令行工具(比如OpenSSH)建立SSH隧道,再用普通的JDBC代码连接本地映射的端口就行。
操作步骤:
- 打开终端,执行这条命令(替换成你的实际信息):
解释:把你本地的5432端口,转发到SSH服务器上的ssh -L 5432:localhost:5432 你的SSH用户名@SSH服务器IPlocalhost:5432(也就是PostgreSQL的默认端口)。执行后输入SSH密码,保持终端窗口打开,隧道就建立好了。 - 然后写普通的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库来实现。
操作步骤:
- 先给项目添加JSch依赖(比如用Maven的话,在
pom.xml里加):<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> - 然后编写代码,先建立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
相关产品推荐
相关产品推荐

