1. 概述
SSH(安全外壳协议)为我们提供了安全访问和管理远程系统的能力,包括执行命令、传输文件以及服务隧道等操作。
通过SSH会话,我们可以建立到远程MySQL数据库的连接。在Java生态中,JSch是最常用的SSH客户端库之一。
本教程将演示如何通过SSH隧道连接到远程服务器本地主机上运行的MySQL数据库。
2. 理解SSH端口转发
端口转发通过SSH连接将本地端口的流量定向到远程服务器的指定端口,实现客户端系统与远程服务器间的数据传输。
当防火墙或其他网络限制阻止直接访问远程服务器的IP和端口时,这种技术特别有用。
在我们的场景中,MySQL服务器运行在远程机器的localhost
上(通常使用3306端口)。虽然技术上可以直接连接远程服务器的IP和MySQL端口,但出于安全考虑通常会被限制。此时,我们可以通过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 = "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();
✅ 分别调用Session
的disconnect()
和Connection
的close()
方法释放资源
❌ 避免资源泄漏,防止潜在内存问题
9. 总结
本文介绍了通过SSH隧道连接远程数据库的方法,重点讲解了本地端口转发技术,并演示了如何通过已建立的SSH会话连接远程MySQL数据库。
完整示例代码可在GitHub仓库中获取。