From 5dc221199ea4f13739207b5cb213837703470864 Mon Sep 17 00:00:00 2001 From: gaoxq <376340421@qq.com> Date: Sat, 10 Jan 2026 23:38:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9F=A5=E7=9C=8B=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/pom.xml | 16 +- .../jeesite/modules/app/Job/biz/hostJob.java | 64 +++--- .../java/com/jeesite/modules/app/Test.java | 10 +- .../jeesite/modules/app/utils/AesUtil.java | 109 +++++++++++ .../modules/app/utils/MyFileUtils.java | 2 + .../jeesite/modules/app/utils/MyUtils.java | 4 + .../jeesite/modules/app/utils/SystemUtil.java | 184 ++++++++++-------- .../jeesite/modules/app/utils/sftpUtils.java | 81 ++++++++ .../com/jeesite/modules/app/utils/vo.java | 41 ---- .../biz/web/BizMonitorAccountController.java | 7 +- 10 files changed, 363 insertions(+), 155 deletions(-) create mode 100644 web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java create mode 100644 web-api/src/main/java/com/jeesite/modules/app/utils/sftpUtils.java delete mode 100644 web-api/src/main/java/com/jeesite/modules/app/utils/vo.java diff --git a/common/pom.xml b/common/pom.xml index 29df84a2..b95774d4 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -29,7 +29,7 @@ cn.hutool hutool-all - 5.8.16 + 5.8.42 @@ -41,7 +41,19 @@ commons-net commons-net - 3.11.0 + 3.11.0 + + + + org.apache.poi + poi + 5.4.1 + + + + org.apache.poi + poi-ooxml + 5.4.1 diff --git a/web-api/src/main/java/com/jeesite/modules/app/Job/biz/hostJob.java b/web-api/src/main/java/com/jeesite/modules/app/Job/biz/hostJob.java index 35932d77..5532125a 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/Job/biz/hostJob.java +++ b/web-api/src/main/java/com/jeesite/modules/app/Job/biz/hostJob.java @@ -1,5 +1,6 @@ package com.jeesite.modules.app.Job.biz; +import com.jcraft.jsch.Session; import com.jeesite.common.config.Global; import com.jeesite.modules.app.dao.info.CpuInfo; import com.jeesite.modules.app.dao.info.DiskInfo; @@ -81,41 +82,46 @@ public class hostJob { public void syncServerInfo(BizMonitorHost host) { BizMonitorAccount monitorAccount = new BizMonitorAccount(); monitorAccount.setHostId(host.getHostId()); + monitorAccount.setUstatus("1"); monitorAccount.setSshUsername("ogsapp"); List accountList = accountService.findList(monitorAccount); if (accountList.size() > 0) { try { BizMonitorAccount account = accountList.get(0); - CpuInfo cpuInfo = SystemUtil.getCpuMemUsage(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword())); - ServerInfo info = SystemUtil.getServerBasicInfo(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword()), host.getIpAddress()); - List diskInfos = SystemUtil.getDiskInfos(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword())); - syncDeviceInfo(host, diskInfos); - BizServerInfo bizServerInfo = new BizServerInfo(); - bizServerInfo.setHostId(host.getHostId()); - List serverInfoList = serverInfoService.findList(bizServerInfo); - BizServerInfo serverInfo = serverInfoList.isEmpty() ? new BizServerInfo() : serverInfoList.get(0); - serverInfo.setUptime(info.getUptime()); - serverInfo.setOs(info.getOs()); - serverInfo.setKernelVersion(info.getKernelVersion()); - serverInfo.setHostname(info.getHostname()); - serverInfo.setIpAddress(info.getIpAddress()); - serverInfo.setCpuModel(info.getCpuModel()); - serverInfo.setMemoryTotal(info.getMemoryTotal()); - serverInfo.setCpuUsage(cpuInfo.getCpuUsage()); - serverInfo.setMemoryUsage(cpuInfo.getMemoryUsage()); - serverInfo.setLastOnlineTime(new Date()); - serverInfo.setHostId(host.getHostId()); - serverInfoService.save(serverInfo); - if (serverInfo.getCpuUsage() >= CPU_RATE) { - BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "CPU预警", 2, serverInfo.getHostname() + "CPU预警", "当前主机CPU已超过" + CPU_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0"); - bizWarningAlertService.save(warningAlert); - } - if (serverInfo.getMemoryUsage() >= MEM_RATE) { - BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "内存预警", 2, serverInfo.getHostname() + "内存预警", "当前主机内存已超过" + MEM_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0"); - bizWarningAlertService.save(warningAlert); + Session session = SystemUtil.getSshSession(account); + if (session.isConnected()) { + CpuInfo cpuInfo = SystemUtil.getCpuMemUsage(session); + ServerInfo info = SystemUtil.getServerBasicInfo(session); + List diskInfos = SystemUtil.getDiskInfos(session); + syncDeviceInfo(host, diskInfos); + BizServerInfo bizServerInfo = new BizServerInfo(); + bizServerInfo.setHostId(host.getHostId()); + List serverInfoList = serverInfoService.findList(bizServerInfo); + BizServerInfo serverInfo = serverInfoList.isEmpty() ? new BizServerInfo() : serverInfoList.get(0); + serverInfo.setUptime(info.getUptime()); + serverInfo.setOs(info.getOs()); + serverInfo.setKernelVersion(info.getKernelVersion()); + serverInfo.setHostname(info.getHostname()); + serverInfo.setIpAddress(info.getIpAddress()); + serverInfo.setCpuModel(info.getCpuModel()); + serverInfo.setMemoryTotal(info.getMemoryTotal()); + serverInfo.setCpuUsage(cpuInfo.getCpuUsage()); + serverInfo.setMemoryUsage(cpuInfo.getMemoryUsage()); + serverInfo.setLastOnlineTime(new Date()); + serverInfo.setHostId(host.getHostId()); + serverInfoService.save(serverInfo); + if (serverInfo.getCpuUsage() >= CPU_RATE) { + BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "CPU预警", 2, serverInfo.getHostname() + "CPU预警", "当前主机CPU已超过" + CPU_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0"); + bizWarningAlertService.save(warningAlert); + } + if (serverInfo.getMemoryUsage() >= MEM_RATE) { + BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "内存预警", 2, serverInfo.getHostname() + "内存预警", "当前主机内存已超过" + MEM_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0"); + bizWarningAlertService.save(warningAlert); + } + SystemUtil.closeSession(session); } } catch (Exception e) { - logger.error(e.getMessage()); + logger.error(e.getMessage(), host); } } } @@ -145,7 +151,7 @@ public class hostJob { bizWarningAlertService.save(warningAlert); } } catch (Exception e) { - logger.error(e.getMessage()); + logger.error(e.getMessage(), host); } } } diff --git a/web-api/src/main/java/com/jeesite/modules/app/Test.java b/web-api/src/main/java/com/jeesite/modules/app/Test.java index ba1d3141..b69d92d9 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/Test.java +++ b/web-api/src/main/java/com/jeesite/modules/app/Test.java @@ -1,8 +1,16 @@ package com.jeesite.modules.app; +import com.jeesite.modules.app.utils.SystemUtil; + +import com.jcraft.jsch.Session; + public class Test { - public static void main(String[] args) { + public static void main(String[] args) throws Exception { + +// Session session = SystemUtil.getSshSession("192.168.31.182", 22, "ogsapp", "WIjYVp3bSNaJ7gK9n9jk7Q=="); +// +// System.out.println(SystemUtil.getServerBasicInfo(session)); } } diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java b/web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java new file mode 100644 index 00000000..789dadda --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java @@ -0,0 +1,109 @@ +package com.jeesite.modules.app.utils; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Arrays; +import java.util.concurrent.ThreadLocalRandom; + +/** + * AES加密解密工具类(CBC/PKCS5Padding) + * 优化说明:修复密钥BUG+解决换行问题+性能优化+安全加固+零依赖 + */ +public class AesUtil { + + + private static final LoggerUtils logger = LoggerUtils.getInstance(); + private static final String AES_KEY_HEX = "AD42F6697B035B7580E4FEF93BE20BAD"; // 你的32位16进制密钥 + private static final String CHARSET = StandardCharsets.UTF_8.name(); + private static final int IV_LENGTH = 16; // AES CBC IV固定16字节 + private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; + private static final String ALGORITHM = "AES"; + + private static final ThreadLocal ENCRYPT_CIPHER = ThreadLocal.withInitial(() -> { + try { + return Cipher.getInstance(TRANSFORMATION); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + private static final ThreadLocal DECRYPT_CIPHER = ThreadLocal.withInitial(() -> { + try { + return Cipher.getInstance(TRANSFORMATION); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + /** + * 加密 + */ + public static String encrypt(String content) { + return encrypt(content, hex2Bytes(AES_KEY_HEX)); + } + + /** + * 解密 + */ + public static String decrypt(String content) { + return decrypt(content, hex2Bytes(AES_KEY_HEX)); + } + + public static String encrypt(String content, byte[] key) { + if (content == null || content.isEmpty()) { + return ""; + } + try { + SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM); + IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(key, IV_LENGTH)); + Cipher cipher = ENCRYPT_CIPHER.get(); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); + byte[] encryptBytes = cipher.doFinal(content.getBytes(CHARSET)); + return Base64.getEncoder().encodeToString(encryptBytes); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String decrypt(String content, byte[] key) { + if (content == null || content.isEmpty()) { + return ""; + } + try { + SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM); + IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(key, IV_LENGTH)); + Cipher cipher = DECRYPT_CIPHER.get(); + cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); + byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(content)); + String result = new String(decryptBytes, CHARSET); + return result.trim(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 32位16进制字符串转16字节数组(解决你的密钥长度BUG的核心方法) + */ + private static byte[] hex2Bytes(String hexStr) { + if (hexStr == null || hexStr.length() % 2 != 0) { + throw new IllegalArgumentException("密钥必须是偶数长度的16进制字符串"); + } + byte[] bytes = new byte[hexStr.length() / 2]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16); + } + return bytes; + } + + /** + * 生成随机16字节IV向量(方案2:安全随机IV,新业务推荐使用) + */ + private static byte[] generateRandomIV() { + byte[] iv = new byte[IV_LENGTH]; + ThreadLocalRandom.current().nextBytes(iv); + return iv; + } +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java b/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java index be593e6f..d85887ac 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/MyFileUtils.java @@ -1,5 +1,7 @@ package com.jeesite.modules.app.utils; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/MyUtils.java b/web-api/src/main/java/com/jeesite/modules/app/utils/MyUtils.java index 76c23679..fcca792e 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/MyUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/MyUtils.java @@ -19,6 +19,10 @@ public class MyUtils { return sb.toString(); } + public static String getPath(String... paths) { + return String.join("/", paths); + } + public static Map convertToTreeNode(BizFolders folder, String parentName) { Map node = new HashMap<>(); diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/SystemUtil.java b/web-api/src/main/java/com/jeesite/modules/app/utils/SystemUtil.java index 42173705..c97d799a 100644 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/SystemUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/SystemUtil.java @@ -1,12 +1,12 @@ package com.jeesite.modules.app.utils; - import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.jeesite.modules.app.dao.info.CpuInfo; import com.jeesite.modules.app.dao.info.DiskInfo; import com.jeesite.modules.app.dao.info.ServerInfo; +import com.jeesite.modules.biz.entity.BizMonitorAccount; import org.springframework.util.StringUtils; import java.io.BufferedReader; @@ -15,167 +15,195 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.*; - +/** + * 服务器系统信息采集工具类(SSH方式) + * 最终优化版:解决Session复用问题,调用方统一管理会话生命周期,杜绝重复关闭 + */ public class SystemUtil { - - // SSH 连接超时时间(毫秒) - private static final int SSH_TIMEOUT = 5000; - + // CPU使用率默认值 + private static final double DEFAULT_USAGE = 0.0; + private static final List FILTER_FILE_SYSTEM = Arrays.asList("dev"); /** * 建立SSH连接 */ - private static Session getSshSession(String host, int port, String username, String password) throws Exception { - JSch jsch = new JSch(); - Session session = jsch.getSession(username, host, port); - session.setPassword(password); - - Properties config = new Properties(); - config.put("StrictHostKeyChecking", "no"); - session.setConfig(config); - - session.setTimeout(SSH_TIMEOUT); - session.connect(); + public static Session getSshSession(BizMonitorAccount account) { + Session session = null; + try { + String passwd = AesUtil.decrypt(account.getSshPassword()); + JSch jsch = new JSch(); + session = jsch.getSession(account.getSshUsername(), account.getIpAddress(), account.getSshPort()); + session.setPassword(passwd); + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + session.setTimeout(account.getTimeoutSeconds()); + session.connect(); + } catch (Exception e) { + System.out.println(e); + } return session; } + // ======================== 统一的资源关闭工具方法 ======================== + /** - * 执行SSH命令并返回结果 + * 安全关闭SSH通道,空指针安全+异常捕获 */ - private static String executeCommand(Session session, String command) throws Exception { - ChannelExec channel = (ChannelExec) session.openChannel("exec"); - channel.setCommand(command); - - InputStream in = channel.getInputStream(); - channel.connect(); - - BufferedReader reader = new BufferedReader( - new InputStreamReader(in, StandardCharsets.UTF_8) - ); - StringBuilder result = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - result.append(line).append("\n"); + private static void closeChannel(ChannelExec channel) { + if (channel != null && channel.isConnected()) { + try { + channel.disconnect(); + } catch (Exception e) { + System.out.println(e); + } } - - reader.close(); - channel.disconnect(); - return result.toString().trim(); } + /** + * 安全关闭SSH会话,空指针安全+异常捕获 + * 【核心】仅提供给调用方,在所有业务查询完成后统一调用! + */ + public static void closeSession(Session session) { + if (session != null && session.isConnected()) { + try { + session.disconnect(); + } catch (Exception e) { + System.out.println(e); + } + } + } + + /** + * 执行SSH命令并返回结果(核心优化,资源闭环+异常安全) + */ + private static String executeCommand(Session session, String command) throws Exception { + if (session == null || !session.isConnected() || !StringUtils.hasText(command)) { + return ""; + } + ChannelExec channel = null; + try { + channel = (ChannelExec) session.openChannel("exec"); + channel.setCommand(command); + try (InputStream in = channel.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { + channel.connect(); + StringBuilder result = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + result.append(line).append("\n"); + } + return result.toString().trim(); + } + } finally { + // 只关闭通道,不关闭会话 + closeChannel(channel); + } + } /** * 获取服务器基础信息 + * ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话 */ - public static ServerInfo getServerBasicInfo(String host, int port, String username, String password, String ipAddress) throws Exception { + public static ServerInfo getServerBasicInfo(Session session) { ServerInfo info = new ServerInfo(); - Session session = null; try { - session = getSshSession(host, port, username, password); - // 主机运行时间 String uptimeResult = executeCommand(session, "uptime"); if (StringUtils.hasText(uptimeResult)) { String[] parts = uptimeResult.split("up "); if (parts.length > 1) { - info.setUptime(parts[1].split(", ")[0]); + String uptime = parts[1].split(",")[0]; + info.setUptime(uptime); } } - // 操作系统 String osResult = executeCommand(session, "cat /etc/os-release | grep PRETTY_NAME | cut -d'=' -f2 | tr -d '\"'"); - info.setOs(osResult.isEmpty() ? "Unknown" : osResult); - + info.setOs(StringUtils.hasText(osResult) ? osResult : "Unknown"); // 内核版本 info.setKernelVersion(executeCommand(session, "uname -r")); - // 主机名 info.setHostname(executeCommand(session, "hostname")); - // IP地址(传入参数) - info.setIpAddress(ipAddress); - + info.setIpAddress(session.getHost()); // CPU型号 String cpuResult = executeCommand(session, "cat /proc/cpuinfo | grep 'model name' | head -n 1 | cut -d: -f2 | sed -e 's/^ *//'"); - info.setCpuModel(cpuResult.isEmpty() ? "Unknown" : cpuResult); - + info.setCpuModel(StringUtils.hasText(cpuResult) ? cpuResult : "Unknown"); // 内存总量 String memResult = executeCommand(session, "free -h | grep Mem | awk '{print $2}'"); - info.setMemoryTotal(memResult.isEmpty() ? "Unknown" : memResult); - - } finally { - if (session != null && session.isConnected()) { - session.disconnect(); - } + info.setMemoryTotal(StringUtils.hasText(memResult) ? memResult : "Unknown"); + } catch (Exception e) { + System.out.println(e); } return info; } /** * 获取CPU和内存使用率 + * ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话 */ - public static CpuInfo getCpuMemUsage(String host, int port, String username, String password) throws Exception { + public static CpuInfo getCpuMemUsage(Session session) { CpuInfo usage = new CpuInfo(); - Session session = null; try { - session = getSshSession(host, port, username, password); - // CPU使用率 String cpuCommand = "top -bn2 | grep '%Cpu' | tail -n1 | awk '{print 100 - $8}'"; String cpuResult = executeCommand(session, cpuCommand); if (StringUtils.hasText(cpuResult)) { usage.setCpuUsage(Double.parseDouble(cpuResult)); + } else { + usage.setCpuUsage(DEFAULT_USAGE); } // 内存使用率 String memCommand = "free | grep Mem | awk '{print $3/$2 * 100}'"; String memResult = executeCommand(session, memCommand); if (StringUtils.hasText(memResult)) { usage.setMemoryUsage(Double.parseDouble(memResult)); + } else { + usage.setMemoryUsage(DEFAULT_USAGE); } - - } finally { - if (session != null && session.isConnected()) { - session.disconnect(); - } + } catch (Exception e) { + System.out.println(e); } return usage; } /** * 获取所有磁盘信息 + * ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话 */ - public static List getDiskInfos(String host, int port, String username, String password) throws Exception { + public static List getDiskInfos(Session session) { List diskInfos = new ArrayList<>(); - Session session = null; try { - session = getSshSession(host, port, username, password); - // 关键修改:强制英文输出 + 调整字段索引 String diskCommand = "LANG=en_US.UTF-8 df -h | awk '{print $1, $6, $2, $3, $5}'"; String diskResult = executeCommand(session, diskCommand); - if (StringUtils.hasText(diskResult)) { String[] lines = diskResult.split("\n"); for (String line : lines) { - // 过滤空行和标题行 if (line.trim().isEmpty() || line.contains("Filesystem")) { continue; } - // 按任意空格分割(兼容多个空格) String[] parts = line.trim().split("\\s+"); if (parts.length >= 5) { + String fileSystem = parts[0]; + boolean isFilter = FILTER_FILE_SYSTEM.stream().anyMatch(fileSystem::contains); + if (isFilter) { + continue; + } + double usage = DEFAULT_USAGE; String usageStr = parts[4].replace("%", "").trim(); - DiskInfo diskInfo = new DiskInfo(parts[0], parts[1], parts[2], parts[3], Double.parseDouble(usageStr)); + if (StringUtils.hasText(usageStr)) { + usage = Double.parseDouble(usageStr); + } + DiskInfo diskInfo = new DiskInfo(parts[0], parts[1], parts[2], parts[3], usage); diskInfos.add(diskInfo); } } } - } finally { - if (session != null && session.isConnected()) { - session.disconnect(); - } + } catch (Exception e) { + System.out.println(e); } return diskInfos; } -} +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/sftpUtils.java b/web-api/src/main/java/com/jeesite/modules/app/utils/sftpUtils.java new file mode 100644 index 00000000..208ba224 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/app/utils/sftpUtils.java @@ -0,0 +1,81 @@ +package com.jeesite.modules.app.utils; + + +import com.jcraft.jsch.ChannelSftp; +import cn.hutool.core.lang.Filter; +import cn.hutool.extra.ssh.JschUtil; +import cn.hutool.extra.ssh.Sftp; +import com.jeesite.modules.biz.entity.BizMonitorAccount; + +import java.io.File; +import java.util.List; +import java.util.regex.Pattern; + +public class sftpUtils { + + private static final LoggerUtils logger = LoggerUtils.getInstance(); + + + public static Filter ruleFilter(String pattern) { + if (pattern == null || pattern.isBlank()) { + return entry -> false; + } + String matchPattern = pattern.trim().toLowerCase(); + String[] ruleArr = matchPattern.split(","); + StringBuilder regexBuilder = new StringBuilder(); + for (int i = 0; i < ruleArr.length; i++) { + String rule = ruleArr[i].trim(); + if (rule.isBlank()) continue; + // 通配符转正则 + String singleRegex = rule.replace(".", "\\.").replace("*", ".*"); + regexBuilder.append("^").append(singleRegex).append("$"); + if (i < ruleArr.length - 1) { + regexBuilder.append("|"); // 多规则用或连接 + } + } + Pattern compilePattern = Pattern.compile(regexBuilder.toString()); + return entry -> { + if (entry == null || entry.getAttrs().isDir()) { + return false; + } + String fileName = entry.getFilename(); + if (fileName == null || fileName.isBlank()) { + return false; + } + return compilePattern.matcher(fileName.toLowerCase()).matches(); + }; + } + + /** + * 上传文件 + */ + public static void fileUpload(BizMonitorAccount account, String getRemotePath, String localFile) { + try { + File file = new File(localFile); + if (file.exists()) { + Sftp sftp = JschUtil.createSftp(account.getIpAddress(), account.getSshPort(), account.getSshUsername(), AesUtil.decrypt(account.getSshPassword())); + sftp.put(localFile, getRemotePath); + sftp.close(); + } + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + + + /** + * 下载文件 + */ + public static void fileDownload(BizMonitorAccount account, String getRemotePath, String filter, String localPath) { + try { + Sftp sftp = JschUtil.createSftp(account.getIpAddress(), account.getSshPort(), account.getSshUsername(), AesUtil.decrypt(account.getSshPassword())); + List files = sftp.ls(getRemotePath, ruleFilter(filter)); + for (String fileName : files) { + sftp.get(MyUtils.getPath(getRemotePath, fileName), localPath); + } + sftp.close(); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } +} diff --git a/web-api/src/main/java/com/jeesite/modules/app/utils/vo.java b/web-api/src/main/java/com/jeesite/modules/app/utils/vo.java deleted file mode 100644 index 69e99bdb..00000000 --- a/web-api/src/main/java/com/jeesite/modules/app/utils/vo.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jeesite.modules.app.utils; - -import com.jeesite.common.codec.AesUtils; - - -public class vo { - - private static final String AES_KEY = "010e06108bb801e85f8738e01c396dd2"; - - /** - * 获取加密Key - */ - public static String getKey() { - return AesUtils.genKeyString(); - } - - - /** - * 加密 - */ - public static String getEncode(String s) { - try { - return AesUtils.encode(s, AES_KEY); - } catch (Exception e) { - System.out.println(e.getMessage()); - return s; - } - } - - /** - * 解密 - */ - public static String getDecode(String s) { - try { - return AesUtils.decode(s, AES_KEY); - } catch (Exception e) { - System.out.println(e.getMessage()); - return s; - } - } -} diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/BizMonitorAccountController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/BizMonitorAccountController.java index efc5eed4..ae7d0d7a 100644 --- a/web-api/src/main/java/com/jeesite/modules/biz/web/BizMonitorAccountController.java +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/BizMonitorAccountController.java @@ -1,9 +1,8 @@ package com.jeesite.modules.biz.web; -import java.util.Date; import java.util.List; -import com.jeesite.modules.app.utils.vo; +import com.jeesite.modules.app.utils.AesUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -91,11 +90,11 @@ public class BizMonitorAccountController extends BaseController { @ResponseBody public String save(@Validated BizMonitorAccount bizMonitorAccount) { if (bizMonitorAccount.getIsNewRecord()) { - bizMonitorAccount.setSshPassword(vo.getEncode(bizMonitorAccount.getSshPassword())); + bizMonitorAccount.setSshPassword(AesUtil.encrypt(bizMonitorAccount.getSshPassword())); } else { BizMonitorAccount account = bizMonitorAccountService.get(bizMonitorAccount.getAccountId()); if (!account.getSshPassword().equals(bizMonitorAccount.getSshPassword())) { - bizMonitorAccount.setSshPassword(vo.getEncode(bizMonitorAccount.getSshPassword())); + bizMonitorAccount.setSshPassword(AesUtil.encrypt(bizMonitorAccount.getSshPassword())); } } bizMonitorAccountService.save(bizMonitorAccount);