1. 概述

SSH(安全外壳协议)为我们提供了安全访问和管理远程系统的能力,包括执行命令、传输文件以及服务隧道等操作。

通过SSH会话,我们可以建立到远程MySQL数据库的连接。在Java生态中,JSch是最常用的SSH客户端库之一。

本教程将演示如何通过SSH隧道连接到远程服务器本地主机上运行的MySQL数据库

2. 理解SSH端口转发

端口转发通过SSH连接将本地端口的流量定向到远程服务器的指定端口,实现客户端系统与远程服务器间的数据传输

当防火墙或其他网络限制阻止直接访问远程服务器的IP和端口时,这种技术特别有用。

在我们的场景中,MySQL服务器运行在远程机器的localhost上(通常使用3306端口)。虽然技术上可以直接连接远程服务器的IP和MySQL端口,但出于安全考虑通常会被限制。此时,我们可以通过SSH本地端口转发建立到数据库的安全连接。

在本地端口转发中,我们在本地机器分配一个可用端口,并将其绑定到远程运行的MySQL服务器端口,从而实现程序与远程服务器间的数据通信。

3. Maven依赖

首先,在pom.xml中添加JSchMySQL连接器依赖:

<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 = "192.168.1.100";
private static final String USER = "admin";
private static final String PRIVATE_KEY = "/home/user/.ssh/id_rsa";
private static final int PORT = 22;

⚠️ 以上代码使用私钥进行身份认证,实际使用时请替换为真实值

接下来定义数据库连接参数:

private static final String DATABASE_HOST = "localhost";
private static final int DATABASE_PORT = 3306;
private static final String DATABASE_USERNAME = "db_user";
private static final String DATABASE_PASSWORD = "secure_password";

MySQL数据库运行在远程机器的localhost上,使用3306端口。我们定义数据库用户名和密码用于连接认证。

5. 创建SSH会话

使用JSch建立SSH会话:

JSch jsch = new JSch();
jsch.addIdentity(PRIVATE_KEY);

这里使用私钥进行身份认证,也可以改用密码认证方式。

创建SSH会话并连接:

Session session = jsch.getSession(USER, HOST, PORT);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();

❌ 禁用主机密钥检查(StrictHostKeyChecking=no)仅适用于测试环境
✅ 生产环境应启用严格的主机密钥验证以确保安全

最后调用connect()方法建立SSH会话。

6. 通过端口转发连接MySQL

使用SSH端口转发隧道连接MySQL:

int port = session.setPortForwardingL(0, DATABASE_HOST, DATABASE_PORT);

通过传入0作为本地端口,程序会动态选择可用端口,将流量转发到远程MySQL服务器的3306端口

端口转发(隧道)使发送到本地端口的流量通过SSH连接转发到远程机器上的MySQL服务器。

使用转发端口连接MySQL:

String databaseUrl = "jdbc:mysql://" + DATABASE_HOST + ":" + port + "/baeldung";
Connection connection = DriverManager.getConnection(databaseUrl, DATABASE_USERNAME, DATABASE_PASSWORD);

在数据库URL中,我们使用转发的本地端口而非远程MySQL服务器的默认端口(3306)。

验证连接是否成功:

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();

✅ 分别调用Sessiondisconnect()Connectionclose()方法释放资源
❌ 避免资源泄漏,防止潜在内存问题

9. 总结

本文介绍了通过SSH隧道连接远程数据库的方法,重点讲解了本地端口转发技术,并演示了如何通过已建立的SSH会话连接远程MySQL数据库。

完整示例代码可在GitHub仓库中获取。


原始标题:Connecting to Remote MySQL Database Through SSH Using Java | Baeldung