Commit 94756eaf78608f9a6f390e0599e18ac5ca9b7893

Authored by 杨鸣坤
1 parent d7b18559

mysql数据库查询预览

... ... @@ -311,6 +311,12 @@
311 311 <artifactId>mysql-connector-java</artifactId>
312 312 <version>8.0.28</version>
313 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 320 </dependencies>
315 321 <build>
316 322 <plugins>
... ...
1 1 package org.thingsboard.server.dao.yunteng.impl;
2 2
  3 +import com.jcraft.jsch.JSch;
  4 +import com.jcraft.jsch.Session;
3 5 import com.zaxxer.hikari.HikariConfig;
4 6 import com.zaxxer.hikari.HikariDataSource;
  7 +import lombok.extern.slf4j.Slf4j;
5 8 import org.apache.commons.lang3.BooleanUtils;
6 9 import org.apache.commons.lang3.StringUtils;
7 10 import org.springframework.stereotype.Service;
8 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 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 20 import java.sql.*;
12 21 import java.util.ArrayList;
13 22 import java.util.List;
  23 +import java.util.Properties;
14 24
15 25 /**
16 26 * mySql类型数据库连接查询
17 27 */
18 28 @Service("MySql")
  29 +@Slf4j
19 30 public class MySqlDbConnectServiceImpl implements BaseDbConnectService {
  31 +
  32 + private static SSLContext sslContext = null;
  33 +
20 34 @Override
21 35 public Object connect(TkDbConnectDTO tkDbConnectDTO) {
22 36 if (BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsh()) && BooleanUtils.isNotTrue(tkDbConnectDTO.isOpenSsl())) {
23 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 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 150 private Object commonConnect(TkDbConnectDTO tkDbConnectDTO) {
30 151 PreparedStatement statement = null;
31 152 ResultSet resultSet = null;
... ... @@ -39,6 +160,11 @@ public class MySqlDbConnectServiceImpl implements BaseDbConnectService {
39 160 config.setPassword(tkDbConnectDTO.getPassword());
40 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 169 config.setMaximumPoolSize(tkDbConnectDTO.getMaxPoolSize()); // 最大连接数
44 170 config.setMinimumIdle(tkDbConnectDTO.getMinIdle()); // 最小空闲连接数
... ...