使用 Java 通过 SSH 连接远程 MySQL 数据库
1、概览
Secure Shell(SSH)允许我们安全地访问和管理远程系统,包括执行命令、传输文件和隧道服务。
我们可以通过 SSH 会话建立与远程 MySQL 数据库的连接。Java 有多个 SSH 客户端,其中最常见的是 Java Secure Channel(JSch)。
本文将带你了解如何通过 SSH 会话连接到运行在远程服务器上的 MySQL 数据库。
2、了解 SSH 端口转发
端口转发允许通过在 SSH 连接上将流量从本地端口重定向到远程服务器上的端口,从而实现客户系统和远程服务器之间的数据传输。
当防火墙或其他限制阻止直接连接远程服务器的 IP 和端口时,这一点尤其有用。
在本例中,MySQL 服务器运行在远程服务器的 localhost 上,通常使用 3306 端口。虽然从技术上讲,可以直接连接到远程服务器的 IP 和 MySQL 端口,但出于安全考虑,这通常会受到限制(3306 端口未开放)。相反,我们可以通过 SSH 使用本地端口转发来建立与数据库的安全连接。
在本地端口转发中,我们在本地机器上分配一个可用端口,并将其与远程运行的 MySQL 服务器端口绑定,以允许我们的程序与远程服务器之间进行数据通信。
3、Maven 依赖
首先,在 pom.xml 中添加 JSch 和 MySQL 驱动依赖:
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.20</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version>
</dependency>
JSch 提供了 Session
等类,这些类对于建立与远程服务器的 SSH 连接至关重要。此外,MySQL 驱动允许我们与运行中的 MySQL 服务器建立连接。
4、连接配置
定义与远程服务器的连接配置:
private static final String HOST = "HOST";
private static final String USER = "USERNAME";
private static final String PRIVATE_KEY = "PATH_TO_PRIVATEKEY";
private static final int PORT = 22;
在上面的代码中,我们定义了创建 SSH 会话所需的凭证。接下来,定义与远程数据库的连接配置:
private static final String DATABASE_HOST = "localhost";
private static final int DATABASE_PORT = 3306;
private static final String DATABASE_USERNAME = "DATABASE_USERNAME";
private static final String DATABASE_PASSWORD = "DATABASE_PASSWORD";
MySQL 数据库运行在远程机器的 localhost 上,使用 3306 端口。我们定义了数据库用户名和密码,用于验证连接。
5、创建 SSH 会话
连接信息定义后,让我们创建一个 JSch 实例来启动与远程服务器的连接:
JSch jsch = new JSch();
jsch.addIdentity(PRIVATE_KEY);
如上,我们使用私钥来验证身份。当然,也可以使用基于密码的身份认证。
接着,创建一个新的 SSH 会话(Session):
Session session = jsch.getSession(USER, HOST, PORT);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
代码如上,我们创建了一个新会话,为了便于测试,我们禁用了 Host Key 检查,但在生产环境中,出于安全考虑应避免这样做。
最后,调用 Session
对象上的 connect()
方法来打开一个新的 SSH 会话。
6、通过端口转发连接 MySQL
接下来,使用 SSH 端口转发来隧道传输 MySQL 端口:
int port = session.setPortForwardingL(0, DATABASE_HOST, DATABASE_PORT);
代码如上,我们调用了 Session
对象上的 setPortForwardingL()
方法来设置本地端口转发。通过传递 0
作为本地端口,程序会动态选择一个可用的本地端口,将流量转发到远程 MySQL 服务器的 3306
端口。
端口转发(隧道)允许发送到本地端口的流量通过 SSH 连接转发到远程计算机上的 MySQL 服务器。
现在,让我们使用转发端口来连接 MySQL 服务器:
String databaseUrl = "jdbc:mysql://" + DATABASE_HOST + ":" + port + "/baeldung";
Connection connection = DriverManager.getConnection(databaseUrl, DATABASE_USERNAME, DATABASE_PASSWORD);
如上,我们使用 JDBC Connection
类建立了与数据库的连接。在数据库 URL 中,我们使用转发的本地端口,而不是远程 MySQL 服务器的默认端口(3306
)。
此外,还要验证连接是否有效,断言与数据库的连接(connection
)不是 null
。
assertNotNull(connection);
7、简单的查询
现在,让我们在已建立的连接上执行一些数据库操作。首先,创建一个表:
String createTableSQL = "CREATE TABLE test_table (id INT, data VARCHAR(255))";
try (Statement statement = connection.createStatement()) {
statement.execute(createTableSQL);
}
如上,在 baeldung
数据库中创建了一个 test_table
表。
接下来,在创建的表中插入一条记录:
String insertDataSQL = "INSERT INTO test_table (id, data) VALUES (1, 'test data')";
try (Statement statement = connection.createStatement()) {
statement.execute(insertDataSQL);
}
最后,断言创建的表已存在于数据库中:
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery("SHOW TABLES LIKE 'test_table'");
return resultSet.next();
}
8、关闭连接
一样的,操作完毕后需要关闭 SSH 会话和数据库连接:
session.disconnect();
connection.close();
如上,在 Session
和 Connection
对象上分别调用了 disconnect()
和 close()
方法,以释放资源,防止潜在的内存泄漏。
9、总结
本文介绍了 SSH 和 SSH 端口转发,以及如何使用 Java 通过 SSH 连接远程 MySQL 数据库。
Ref:https://www.baeldung.com/java-ssh-remote-mysql-db-connection