Commit 94756eaf78608f9a6f390e0599e18ac5ca9b7893

Authored by 杨鸣坤
1 parent d7b18559

mysql数据库查询预览

@@ -311,6 +311,12 @@ @@ -311,6 +311,12 @@
311 <artifactId>mysql-connector-java</artifactId> 311 <artifactId>mysql-connector-java</artifactId>
312 <version>8.0.28</version> 312 <version>8.0.28</version>
313 </dependency> 313 </dependency>
  314 + <!-- JSch for SSH -->
  315 + <dependency>
  316 + <groupId>com.jcraft</groupId>
  317 + <artifactId>jsch</artifactId>
  318 + <version>0.1.55</version>
  319 + </dependency>
314 </dependencies> 320 </dependencies>
315 <build> 321 <build>
316 <plugins> 322 <plugins>
1 package org.thingsboard.server.dao.yunteng.impl; 1 package org.thingsboard.server.dao.yunteng.impl;
2 2
  3 +import com.jcraft.jsch.JSch;
  4 +import com.jcraft.jsch.Session;
3 import com.zaxxer.hikari.HikariConfig; 5 import com.zaxxer.hikari.HikariConfig;
4 import com.zaxxer.hikari.HikariDataSource; 6 import com.zaxxer.hikari.HikariDataSource;
  7 +import lombok.extern.slf4j.Slf4j;
5 import org.apache.commons.lang3.BooleanUtils; 8 import org.apache.commons.lang3.BooleanUtils;
6 import org.apache.commons.lang3.StringUtils; 9 import org.apache.commons.lang3.StringUtils;
7 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
8 import org.thingsboard.server.common.data.yunteng.dto.TkDbConnectDTO; 11 import org.thingsboard.server.common.data.yunteng.dto.TkDbConnectDTO;
  12 +import org.thingsboard.server.common.data.yunteng.dto.TkDbConnectSshDTO;
  13 +import org.thingsboard.server.common.data.yunteng.dto.TkDbConnectSslDTO;
9 import org.thingsboard.server.dao.yunteng.service.BaseDbConnectService; 14 import org.thingsboard.server.dao.yunteng.service.BaseDbConnectService;
10 15
  16 +import javax.net.ssl.SSLContext;
  17 +import javax.net.ssl.TrustManagerFactory;
  18 +import java.io.FileInputStream;
  19 +import java.security.KeyStore;
11 import java.sql.*; 20 import java.sql.*;
12 import java.util.ArrayList; 21 import java.util.ArrayList;
13 import java.util.List; 22 import java.util.List;
  23 +import java.util.Properties;
14 24
15 /** 25 /**
16 * mySql类型数据库连接查询 26 * mySql类型数据库连接查询
17 */ 27 */
18 @Service("MySql") 28 @Service("MySql")
  29 +@Slf4j
19 public class MySqlDbConnectServiceImpl implements BaseDbConnectService { 30 public class MySqlDbConnectServiceImpl implements BaseDbConnectService {
  31 +
  32 + private static SSLContext sslContext = null;
  33 +
20 @Override 34 @Override
21 public Object connect(TkDbConnectDTO tkDbConnectDTO) { 35 public Object connect(TkDbConnectDTO tkDbConnectDTO) {
22 if (BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsl())) { 36 if (BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsl())) {
23 return commonConnect(tkDbConnectDTO); 37 return commonConnect(tkDbConnectDTO);
  38 + } else if (BooleanUtils.isTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsl())) {
  39 + return sshConnect(tkDbConnectDTO);
  40 + } else if (BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isTrue(tkDbConnectDTO.isOpenSsl())) {
  41 + return sslConnect(tkDbConnectDTO);
  42 + } else if (BooleanUtils.isTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isTrue(tkDbConnectDTO.isOpenSsl())) {
  43 + return sshAndSslConnect(tkDbConnectDTO);
  44 + }
  45 +
  46 + return null;
  47 + }
  48 +
  49 + private Object sshAndSslConnect(TkDbConnectDTO tkDbConnectDTO) {
  50 + try {
  51 + // 1. 建立SSH隧道
  52 + int localPort = setupSSHTunnel(tkDbConnectDTO.getSsh(), tkDbConnectDTO);
  53 + // 配置SSL
  54 + TkDbConnectSslDTO ssl = tkDbConnectDTO.getSsl();
  55 + if (ssl.getCaCert() != null) {
  56 + sslContext = createSSLContext(ssl.getClientCert(), ssl.getClientKey());
  57 + }
  58 +
  59 + String jdbcUrl = "jdbc:mysql://localhost:" + localPort + "/" + tkDbConnectDTO.getDbName() +
  60 + "?useSSL=true" +
  61 + "&requireSSL=true" +
  62 + "&verifyServerCertificate=" + ssl.isVerifyCaCert() +
  63 + "&enabledTLSProtocols=TLSv1.2,TLSv1.3";
  64 + tkDbConnectDTO.setUrl(jdbcUrl);
  65 + return commonConnect(tkDbConnectDTO);
  66 + } catch (Exception e) {
  67 + log.error("sshAndSslConnect occur error!", e);
  68 + e.printStackTrace();
  69 + }
  70 +
  71 + return null;
  72 + }
  73 +
  74 + private Object sslConnect(TkDbConnectDTO tkDbConnectDTO) {
  75 + try {
  76 + TkDbConnectSslDTO ssl = tkDbConnectDTO.getSsl();
  77 + // 配置SSL
  78 + if (ssl.getCaCert() != null) {
  79 + sslContext = createSSLContext(ssl.getClientCert(), ssl.getClientKey());
  80 + }
  81 +
  82 + String jdbcUrl = tkDbConnectDTO.getUrl()
  83 + + "?useSSL=true&"
  84 + + "requireSSL=true&"
  85 + + "verifyServerCertificate=" + ssl.isVerifyCaCert() + "&"
  86 + + "enabledTLSProtocols=TLSv1.2,TLSv1.3";
  87 + tkDbConnectDTO.setUrl(jdbcUrl);
  88 + return commonConnect(tkDbConnectDTO);
  89 + } catch (Exception e) {
  90 + log.error("sslConnect occur error!", e);
  91 + e.printStackTrace();
24 } 92 }
25 93
26 return null; 94 return null;
27 } 95 }
28 96
  97 + private static SSLContext createSSLContext(String certPath, String certPassword)
  98 + throws Exception {
  99 + KeyStore keyStore = KeyStore.getInstance("PKCS12");
  100 + try (FileInputStream fis = new FileInputStream(certPath)) {
  101 + keyStore.load(fis, certPassword.toCharArray());
  102 + }
  103 +
  104 + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  105 + tmf.init(keyStore);
  106 +
  107 + SSLContext sslContext = SSLContext.getInstance("TLS");
  108 + sslContext.init(null, tmf.getTrustManagers(), null);
  109 + return sslContext;
  110 + }
  111 +
  112 + private Object sshConnect(TkDbConnectDTO tkDbConnectDTO) {
  113 + try {
  114 + // 1. 建立SSH隧道
  115 + int localPort = setupSSHTunnel(tkDbConnectDTO.getSsh(), tkDbConnectDTO);
  116 + tkDbConnectDTO.setUrl("jdbc:mysql://localhost:" + localPort + "/" + tkDbConnectDTO.getDbName());
  117 + return commonConnect(tkDbConnectDTO);
  118 + } catch (Exception e) {
  119 + log.info("sshConnect occur error!", e);
  120 + e.printStackTrace();
  121 + }
  122 +
  123 + return null;
  124 + }
  125 +
  126 + private int setupSSHTunnel(TkDbConnectSshDTO ssh, TkDbConnectDTO tkDbConnectDTO) throws Exception {
  127 + JSch jsch = new JSch();
  128 + Session sshSession = jsch.getSession(ssh.getSshName(), ssh.getIp(), Integer.parseInt(ssh.getPort()));
  129 + if (StringUtils.isBlank(ssh.getVerifyMethod()) || "PASSWORD".equals(ssh.getVerifyMethod())) {
  130 + sshSession.setPassword(ssh.getSshPassword());
  131 + } else {
  132 + // 可以添加密钥文件(替代密码)
  133 + jsch.addIdentity(ssh.getPrivateKey());
  134 + }
  135 +
  136 + Properties config = new Properties();
  137 + config.put("StrictHostKeyChecking", "no");
  138 + sshSession.setConfig(config);
  139 +
  140 + // 设置SSH连接超时
  141 + sshSession.connect(tkDbConnectDTO.getConnectTimeout());
  142 +
  143 + // 分配本地端口(0表示自动选择)
  144 + int localPort = sshSession.setPortForwardingL(0, tkDbConnectDTO.getIp(), Integer.parseInt(tkDbConnectDTO.getPort()));
  145 + System.out.println("SSH隧道建立成功,本地端口: " + localPort);
  146 +
  147 + return localPort;
  148 + }
  149 +
29 private Object commonConnect(TkDbConnectDTO tkDbConnectDTO) { 150 private Object commonConnect(TkDbConnectDTO tkDbConnectDTO) {
30 PreparedStatement statement = null; 151 PreparedStatement statement = null;
31 ResultSet resultSet = null; 152 ResultSet resultSet = null;
@@ -39,6 +160,11 @@ public class MySqlDbConnectServiceImpl implements BaseDbConnectService { @@ -39,6 +160,11 @@ public class MySqlDbConnectServiceImpl implements BaseDbConnectService {
39 config.setPassword(tkDbConnectDTO.getPassword()); 160 config.setPassword(tkDbConnectDTO.getPassword());
40 config.setDriverClassName("com.mysql.cj.jdbc.Driver"); 161 config.setDriverClassName("com.mysql.cj.jdbc.Driver");
41 162
  163 + // SSL配置
  164 + if (sslContext != null) {
  165 + config.addDataSourceProperty("sslContext", sslContext);
  166 + }
  167 +
42 // 连接池配置 168 // 连接池配置
43 config.setMaximumPoolSize(tkDbConnectDTO.getMaxPoolSize()); // 最大连接数 169 config.setMaximumPoolSize(tkDbConnectDTO.getMaxPoolSize()); // 最大连接数
44 config.setMinimumIdle(tkDbConnectDTO.getMinIdle()); // 最小空闲连接数 170 config.setMinimumIdle(tkDbConnectDTO.getMinIdle()); // 最小空闲连接数