尝试通过 SSH 隧道连接 PostgreSQL 时连接尝试失败。我将 Java 与 jsch 库一起使用
The connection attempt failed when try connect PostgreSQL via SSH tunnel. I using Java with jsch lib
我在成功连接 SSH 后尝试连接到 PostgreSQL 数据库时遇到问题。
我正在使用 Java + JSCH 库来帮助通过 SSH 隧道连接到 DB PostgreSQL。
请帮忙看看我的代码:
public static Connection connectDBAWS(String ipAddress, int port, String dbName, String username, String password, String tunnelHost, int tunnelPort, String tunnelUsername, String tunnelPassword) {
Connection connection;
Session session;
try {
//SSH TUNNEL connection
JSch jsch = new JSch();
session = jsch.getSession(tunnelUsername, tunnelHost, 22);
session.setPassword(tunnelPassword);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("Connected Successfully");
int assinged_port = session.setPortForwardingL(port, tunnelHost, tunnelPort);
System.out.println("assinged_port -> " + assinged_port);
System.out.println("Port Forwarded");
//DB connection
String dbUrl = "jdbc:postgresql://" + ipAddress + ":" + assinged_port + "/" + dbName;
Class.forName("org.postgresql.Driver");;
connection = DriverManager.getConnection(dbUrl, username, password);
System.out.println("connect DB success");
} catch (Exception e) {
connection = null;
e.printStackTrace();
}
return connection;
}
在以下步骤抛出异常:
connection = DriverManager.getConnection(dbUrl, username, password);
这是结果:
Connected Successfully
assinged_port -> 5432
Port Forwarded
org.postgresql.util.PSQLException: The connection attempt failed.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
at org.postgresql.Driver.makeConnection(Driver.java:454)
at org.postgresql.Driver.connect(Driver.java:256)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
...
我使用上面的值手动连接 PostgreSQL,使用 pgAdmin4,并成功连接:
See configuration image here.
请有人可以提供一些理想的方法来修复我的代码。
int assinged_port = session.setPortForwardingL(port, tunnelHost, tunnelPort);
我认为问题在于您不知道这些值中的任何一个应该意味着什么。您在错误的地方传递了错误的值。例如,assigned_port
值在这里毫无意义。
L 型端口转发背后的想法是:
- 连接到 本地端口
port
通过 SSH 连接到您连接的服务器...
- 然后弹出另一边。然后另一端将连接到主机
tunnelHost
,端口 tunnelPort
,因此转发将继续。
鉴于它的工作原理,名称和值都是错误的。
tunnelPort
肯定是'port of the tunnel'。换句话说,这是本地端口 - 它应该是传递给 setPortForwardingL
的 第一个 参数,而不是最后一个
- 第二个和第三个参数告诉远程 SSH 服务器要连接到什么,完成端口。鉴于您正在通过 SSH 连接到服务器,您不希望服务器随后连接到服务器。这有时有效,但通常无效,这取决于网络会话。你反而想要
localhost
那里!请记住,server/port 组合 连接到服务器端 。 'localhost' 这里的值指的是在服务器 上解析为本地主机 的内容。这就是你想要的。
- 最后,SSH 隧道的要点是您在本地机器上有一个 local 端口 - 这就是隧道 'starts' 的位置。因此,您希望 JDBC 连接 到本地主机 。您正在连接到
ipAddress
,无论它是什么。
所以,固定码是:
// The host in the cloud running an SSH server that you're connecting to.
String tunnelHost = "mypsqlserverinthecloud.com";
// The host in the cloud with the PSQL server, as you would
// connect to it from tunnelHost! In most cases this should be localhost!
String psqlHost = "localhost";
int psqlPort = 5432; // port of the psql server on the psql box.
int tunnelPort = 1234; // pick whatever you want here.
String username = "LDT";
String password = "hunter2"; // please see note below!
JSch session = new JSch();
session = jsch.getSession(username, tunnelHost, 22);
// Why aren't you using key-based authentication?
// Why aren't you using strict host key checking?
// None of this is particularly secure as a consequence!
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("Connected Successfully");
session.setPortForwardingL(tunnelPort, psqlHost, psqlPort);
System.out.println("Port Forwarded");
String dbUrl = "jdbc:postgresql://localhost:" + tunnelPort + "/" + dbName;
// you do not need Class.forName. Not for the past 20 years.
// what stone age tutorial are you following?
// Consider that it probably contains more bad / obsolete advice!
Connection con = DriverManager.getConnection(dbUrl, username, password);
System.out.println("connect DB success");
这里还有多个代码风格错误。例如,如果您曾经编写过捕获异常的代码,e.printStackTrace()
它,然后继续运行,请停止您正在做的事情。这是可怕的,可怕的错误处理。只需让这些方法抛出已检查的异常即可。连接到 DB 的方法应该 抛出 SQLException 并且可能抛出 IOException。如果你真的不能那样做或者不想那样做,那么要么处理异常,对于 90% 以上的异常,你什么都想不到(这很正常),它应该总是以 throw
.所以不是:
} catch (SQLException e) {
e.printStackTrace();
return null; // idiotic. Do not do this.
}
相反,执行:
public void theMethodThisCodeWasIn() throws SQLException {
或者如果你不能,请执行:
} catch (SQLException e) {
throw new RuntimeException("Not handled", e);
}
例如。最好写下如何处理异常;抛出类型 RuntimeException
是最后的手段。但仍然 miles 优于 e.printStackTrace();
并继续 运行!
我在成功连接 SSH 后尝试连接到 PostgreSQL 数据库时遇到问题。 我正在使用 Java + JSCH 库来帮助通过 SSH 隧道连接到 DB PostgreSQL。 请帮忙看看我的代码:
public static Connection connectDBAWS(String ipAddress, int port, String dbName, String username, String password, String tunnelHost, int tunnelPort, String tunnelUsername, String tunnelPassword) {
Connection connection;
Session session;
try {
//SSH TUNNEL connection
JSch jsch = new JSch();
session = jsch.getSession(tunnelUsername, tunnelHost, 22);
session.setPassword(tunnelPassword);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("Connected Successfully");
int assinged_port = session.setPortForwardingL(port, tunnelHost, tunnelPort);
System.out.println("assinged_port -> " + assinged_port);
System.out.println("Port Forwarded");
//DB connection
String dbUrl = "jdbc:postgresql://" + ipAddress + ":" + assinged_port + "/" + dbName;
Class.forName("org.postgresql.Driver");;
connection = DriverManager.getConnection(dbUrl, username, password);
System.out.println("connect DB success");
} catch (Exception e) {
connection = null;
e.printStackTrace();
}
return connection;
}
在以下步骤抛出异常:
connection = DriverManager.getConnection(dbUrl, username, password);
这是结果:
Connected Successfully
assinged_port -> 5432
Port Forwarded
org.postgresql.util.PSQLException: The connection attempt failed.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
at org.postgresql.Driver.makeConnection(Driver.java:454)
at org.postgresql.Driver.connect(Driver.java:256)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
...
我使用上面的值手动连接 PostgreSQL,使用 pgAdmin4,并成功连接: See configuration image here.
请有人可以提供一些理想的方法来修复我的代码。
int assinged_port = session.setPortForwardingL(port, tunnelHost, tunnelPort);
我认为问题在于您不知道这些值中的任何一个应该意味着什么。您在错误的地方传递了错误的值。例如,assigned_port
值在这里毫无意义。
L 型端口转发背后的想法是:
- 连接到 本地端口
port
通过 SSH 连接到您连接的服务器... - 然后弹出另一边。然后另一端将连接到主机
tunnelHost
,端口tunnelPort
,因此转发将继续。
鉴于它的工作原理,名称和值都是错误的。
tunnelPort
肯定是'port of the tunnel'。换句话说,这是本地端口 - 它应该是传递给setPortForwardingL
的 第一个 参数,而不是最后一个- 第二个和第三个参数告诉远程 SSH 服务器要连接到什么,完成端口。鉴于您正在通过 SSH 连接到服务器,您不希望服务器随后连接到服务器。这有时有效,但通常无效,这取决于网络会话。你反而想要
localhost
那里!请记住,server/port 组合 连接到服务器端 。 'localhost' 这里的值指的是在服务器 上解析为本地主机 的内容。这就是你想要的。 - 最后,SSH 隧道的要点是您在本地机器上有一个 local 端口 - 这就是隧道 'starts' 的位置。因此,您希望 JDBC 连接 到本地主机 。您正在连接到
ipAddress
,无论它是什么。
所以,固定码是:
// The host in the cloud running an SSH server that you're connecting to.
String tunnelHost = "mypsqlserverinthecloud.com";
// The host in the cloud with the PSQL server, as you would
// connect to it from tunnelHost! In most cases this should be localhost!
String psqlHost = "localhost";
int psqlPort = 5432; // port of the psql server on the psql box.
int tunnelPort = 1234; // pick whatever you want here.
String username = "LDT";
String password = "hunter2"; // please see note below!
JSch session = new JSch();
session = jsch.getSession(username, tunnelHost, 22);
// Why aren't you using key-based authentication?
// Why aren't you using strict host key checking?
// None of this is particularly secure as a consequence!
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("Connected Successfully");
session.setPortForwardingL(tunnelPort, psqlHost, psqlPort);
System.out.println("Port Forwarded");
String dbUrl = "jdbc:postgresql://localhost:" + tunnelPort + "/" + dbName;
// you do not need Class.forName. Not for the past 20 years.
// what stone age tutorial are you following?
// Consider that it probably contains more bad / obsolete advice!
Connection con = DriverManager.getConnection(dbUrl, username, password);
System.out.println("connect DB success");
这里还有多个代码风格错误。例如,如果您曾经编写过捕获异常的代码,e.printStackTrace()
它,然后继续运行,请停止您正在做的事情。这是可怕的,可怕的错误处理。只需让这些方法抛出已检查的异常即可。连接到 DB 的方法应该 抛出 SQLException 并且可能抛出 IOException。如果你真的不能那样做或者不想那样做,那么要么处理异常,对于 90% 以上的异常,你什么都想不到(这很正常),它应该总是以 throw
.所以不是:
} catch (SQLException e) {
e.printStackTrace();
return null; // idiotic. Do not do this.
}
相反,执行:
public void theMethodThisCodeWasIn() throws SQLException {
或者如果你不能,请执行:
} catch (SQLException e) {
throw new RuntimeException("Not handled", e);
}
例如。最好写下如何处理异常;抛出类型 RuntimeException
是最后的手段。但仍然 miles 优于 e.printStackTrace();
并继续 运行!