引言
在项目开发过程中,遇到了连接数据库时需要使用ssh公钥的情况。在本地使用navicat可以直接通过可视化界面去进行ssh的连接,但是在java中无法直接去进行连接。
后来经过查询资料,发现必须要在java中编写相关配置文件后才可以正常连接。
问题解决
原理:
程序在本机创建ssh连接
,连接到ssh server,然后再发送数据库操作指令,指令会被转发到目标数据库服务器上,返回操作结果**前提:**项目已经配置好mysql连接所需要参数
**注意:**我演示的是使用ssh的公钥模式进行连接,如果需要使用密码模式进行连接,需要打开和关闭某些注释
-
引入依赖
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency>
-
编写ssh连接配置类
package com.lzj.config; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import java.util.Properties; /** * <p> * SSH连接配置类 * </p> * * @author:雷子杰 * @date:2023/3/4 */ public class SSHConnectionConfig { //本地的ssh中的knownhost文件路径 private String SSH_PATH_FILE_KNOWN_HOSTS = "C:\\Users\\86158\\.ssh\\known_hosts"; //本地的ssh密钥路径 private String SSH_PATH_FILE_PRIVATE_KEY = "**********************************"; //ssh连接的用户名 private String SSH_USER = "******"; //ssh远程连接的ip地址 private String SSH_REMOTE_SERVER = "65.115.26.30"; //ssh连接的端口号,一般默认为22 private Integer SSH_REMOTE_PORT = 22; //SSH使用密码 //private String sshPassword; //本地mysql发起连接的IP地址 private String MYSQL_REMOTE_SERVER = "127.0.0.1"; //本地数据库连接时用的端口号(不能填3306) private Integer LOCAl_PORT = 3307; //远程数据库端口用的端口号 private Integer REMOTE_PORT = 3309; //com.jcraft.jsch.Session; private Session session; /** * 关闭ssh连接 */ public void closeSSH() { session.disconnect(); } /** * 创建ssh连接 */ public void createSSH() throws JSchException { JSch jSch = new JSch(); //下面这两个设置是在公钥模式需要设置的,非公钥模式不需要进行设置 //设置known_hosts文件路径,如:~/.ssh/known_hosts(known_hosts中存储是已认证的远程主机host key) jSch.setKnownHosts(SSH_PATH_FILE_KNOWN_HOSTS); //设置私钥 jSch.addIdentity(SSH_PATH_FILE_PRIVATE_KEY); session = jSch.getSession(SSH_USER, SSH_REMOTE_SERVER, SSH_REMOTE_PORT); //如果是密码模式需要设置密码 //session.setPassword(sshPassword); //设置连接过程不校验known_hosts文件中的信息 Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); //ssh 建立连接! session.connect(); //根据安全策略,您必须通过转发端口进行连接 session.setPortForwardingL(LOCAl_PORT, MYSQL_REMOTE_SERVER, REMOTE_PORT); } }
-
编写监听器
注意:
- Listener类使用@WebListener注解;
- SpringBoot的启动类需要增加
@ServletComponentScan
用于扫描加载Listener类;
经过我的尝试,发现如果使用了
@Component
注解,就算不使用@WebListener
也同样可以完成监听功能package com.lzj.config; import org.springframework.stereotype.Component; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; /** * <p> * * </p> * * @author:雷子杰 * @date:2023/3/4 */ @Component//尽量加上这个 @WebListener//声明为监听器 public class MyContextListener implements ServletContextListener { private SSHConnectionConfig sshConnectionConfig; public MyContextListener() { super(); } @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("Context initialized ... !"); try { sshConnectionConfig = new SSHConnectionConfig(); sshConnectionConfig.createSSH(); } catch (Throwable e) { e.printStackTrace(); // 连接失败 } } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("Context destroyed ... !"); sshConnectionConfig.closeSSH();//断开ssh连接 } }
-
注意可能需要修改你的
mysql连接配置
可以看见我的的url中的
localhost:3307
,这个ip和端口号是根据你编写的ssh配置类
中MYSQL_REMOTE_SERVER
和LOCAl_PORT
来的,你可能需要进行修改spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver username: root password: ****** url: jdbc:mysql://localhost:3307/leopard-vendor_cloud?autoReconnect=true&useUnicode=true&useSSL=false
-
测试
编写一个测试类测试数据库的连接
package com.lzj; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.sql.DataSource; import java.sql.SQLException; /** * <p> * * </p> * * @author:雷子杰 * @date:2023/3/3 */ @SpringBootTest(classes = SpringbootDetabaseApplication.class) @RunWith(SpringRunner.class) public class InitTest { @Autowired private DataSource dataSource; @Test public void testDataSource() throws SQLException { System.out.println(dataSource.getConnection()); } }
测试结果如下:
可以发现控制台正常输出了连接相关信息
总结
**注意:**数据库连接地址由原来的123.mysql.com:3306改为127.0.0.1:3307,这样子,ssh连接会为每一个127.0.0.1:3307上的操作转发到123.mysql.com:3306上去,便可以正常操作数据库了。ssh连接的创建,可以采用私钥的方式,亦可以采用用户名密码的方式。
文章评论