🔨 优化传输模块日志逻辑.

This commit is contained in:
lijiahangmax
2025-06-30 21:59:24 +08:00
parent 700b6d221d
commit 5dcd8cbad2
13 changed files with 96 additions and 47 deletions

View File

@@ -22,10 +22,8 @@
*/ */
package org.dromara.visor.module.common.utils; package org.dromara.visor.module.common.utils;
import cn.orionsec.kit.lang.constant.Letters;
import cn.orionsec.kit.lang.utils.Booleans; import cn.orionsec.kit.lang.utils.Booleans;
import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.net.host.sftp.SftpExecutor; import cn.orionsec.kit.net.host.sftp.SftpExecutor;
import cn.orionsec.kit.net.host.sftp.SftpFile; import cn.orionsec.kit.net.host.sftp.SftpFile;
import cn.orionsec.kit.spring.SpringHolder; import cn.orionsec.kit.spring.SpringHolder;
@@ -69,21 +67,4 @@ public class SftpUtils {
} }
} }
/**
* 获取移动目标路径
*
* @param source source
* @param target target
* @return absolute target
*/
public static String getAbsoluteTargetPath(String source, String target) {
if (target.charAt(0) == Letters.SLASH) {
// 绝对路径
return Files1.getPath(Files1.normalize(target));
} else {
// 相对路径
return Files1.getPath(Files1.normalize(Files1.getPath(source + "/../" + target)));
}
}
} }

View File

@@ -74,15 +74,15 @@ public class TerminalOperatorType extends InitializingOperatorTypes {
new OperatorType(OperatorRiskLevel.L, SFTP_MKDIR, "创建文件夹 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.L, SFTP_MKDIR, "创建文件夹 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.L, SFTP_TOUCH, "创建文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.L, SFTP_TOUCH, "创建文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_MOVE, "移动文件 ${hostName} <sb>${path}</sb> 至 <sb>${target}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_MOVE, "移动文件 ${hostName} <sb>${path}</sb> 至 <sb>${target}</sb>"),
new OperatorType(OperatorRiskLevel.H, SFTP_REMOVE, "删除文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.H, SFTP_REMOVE, "删除文件 ${hostName} ${count}个\n<sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.H, SFTP_TRUNCATE, "截断文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.H, SFTP_TRUNCATE, "截断文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_CHMOD, "文件提权 ${hostName} <sb>${path}</sb> <sb>${mod}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_CHMOD, "文件提权 ${hostName} <sb>${path}</sb> <sb>${mod}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_CHOWN, "修改文件归属 ${hostName} <sb>${path}</sb> <sb>${id}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_CHOWN, "修改文件归属 ${hostName} <sb>${path}</sb> <sb>${id}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_CHGRP, "修改文件分组 ${hostName} <sb>${path}</sb> <sb>${id}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_CHGRP, "修改文件分组 ${hostName} <sb>${path}</sb> <sb>${id}</sb>"),
new OperatorType(OperatorRiskLevel.L, SFTP_GET_CONTENT, "获取文件内容 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.L, SFTP_GET_CONTENT, "获取文件内容 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_SET_CONTENT, "修改文件内容 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_SET_CONTENT, "修改文件内容 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_UPLOAD, "上传文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_UPLOAD, "上传文件 ${hostName} (${count}个)\n<sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, SFTP_DOWNLOAD, "下载文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.M, SFTP_DOWNLOAD, "下载文件 ${hostName} (${count}个)\n<sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, RDP_UPLOAD, "上传文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.M, RDP_UPLOAD, "上传文件 ${hostName} <sb>${path}</sb>"),
new OperatorType(OperatorRiskLevel.M, RDP_DOWNLOAD, "下载文件 ${hostName} <sb>${path}</sb>"), new OperatorType(OperatorRiskLevel.M, RDP_DOWNLOAD, "下载文件 ${hostName} <sb>${path}</sb>"),
}; };

View File

@@ -29,6 +29,7 @@ import org.dromara.visor.module.terminal.handler.terminal.model.request.SftpDown
import org.dromara.visor.module.terminal.handler.terminal.model.response.SftpFileVO; import org.dromara.visor.module.terminal.handler.terminal.model.response.SftpFileVO;
import org.dromara.visor.module.terminal.handler.terminal.sender.ISftpTerminalSender; import org.dromara.visor.module.terminal.handler.terminal.sender.ISftpTerminalSender;
import org.dromara.visor.module.terminal.handler.terminal.session.ISftpSession; import org.dromara.visor.module.terminal.handler.terminal.session.ISftpSession;
import org.dromara.visor.module.terminal.utils.SftpFileUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Arrays; import java.util.Arrays;
@@ -50,7 +51,7 @@ public class SftpDownloadFlatDirectoryHandler extends AbstractTerminalHandler<IS
// 获取会话 // 获取会话
String sessionId = props.getId(); String sessionId = props.getId();
ISftpSession session = terminalManager.getSession(props.getId()); ISftpSession session = terminalManager.getSession(props.getId());
String[] paths = payload.getPath().split("\\|"); String[] paths = SftpFileUtils.fromMultiPaths(payload.getPath());
log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths)); log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;
List<SftpFileVO> files = Lists.empty(); List<SftpFileVO> files = Lists.empty();

View File

@@ -24,12 +24,14 @@ package org.dromara.visor.module.terminal.handler.terminal.handler;
import cn.orionsec.kit.lang.utils.collect.Maps; import cn.orionsec.kit.lang.utils.collect.Maps;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.constant.Const;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs; import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.module.terminal.define.operator.TerminalOperatorType; import org.dromara.visor.module.terminal.define.operator.TerminalOperatorType;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps; import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.model.request.SftpBaseRequest; import org.dromara.visor.module.terminal.handler.terminal.model.request.SftpBaseRequest;
import org.dromara.visor.module.terminal.handler.terminal.sender.ISftpTerminalSender; import org.dromara.visor.module.terminal.handler.terminal.sender.ISftpTerminalSender;
import org.dromara.visor.module.terminal.handler.terminal.session.ISftpSession; import org.dromara.visor.module.terminal.handler.terminal.session.ISftpSession;
import org.dromara.visor.module.terminal.utils.SftpFileUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Arrays; import java.util.Arrays;
@@ -49,11 +51,11 @@ public class SftpRemoveHandler extends AbstractTerminalHandler<ISftpTerminalSend
@Override @Override
public void handle(TerminalChannelProps props, ISftpTerminalSender sender, SftpBaseRequest payload) { public void handle(TerminalChannelProps props, ISftpTerminalSender sender, SftpBaseRequest payload) {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
String path = payload.getPath(); String[] paths = SftpFileUtils.fromMultiPaths(payload.getPath());
String path = String.join(Const.LF, paths);
String sessionId = props.getId(); String sessionId = props.getId();
// 获取会话 // 获取会话
ISftpSession session = terminalManager.getSession(sessionId); ISftpSession session = terminalManager.getSession(sessionId);
String[] paths = path.split("\\|");
log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths)); log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;
// 删除 // 删除
@@ -69,6 +71,7 @@ public class SftpRemoveHandler extends AbstractTerminalHandler<ISftpTerminalSend
// 保存操作日志 // 保存操作日志
Map<String, Object> extra = Maps.newMap(); Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path); extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.COUNT, paths.length);
this.saveOperatorLog(props, this.saveOperatorLog(props,
extra, TerminalOperatorType.SFTP_REMOVE, extra, TerminalOperatorType.SFTP_REMOVE,
startTime, ex); startTime, ex);

View File

@@ -129,6 +129,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<ITerminalSen
this.updateTerminalConnectLog(logId, null, null); this.updateTerminalConnectLog(logId, null, null);
// 发送设置信息 // 发送设置信息
sender.sendSetInfo(TerminalSetInfo.builder() sender.sendSetInfo(TerminalSetInfo.builder()
.logId(logId)
.address(connectConfig.getHostAddress()) .address(connectConfig.getHostAddress())
.port(connectConfig.getHostPort()) .port(connectConfig.getHostPort())
.username(connectConfig.getUsername()) .username(connectConfig.getUsername())

View File

@@ -41,6 +41,11 @@ import lombok.experimental.SuperBuilder;
@AllArgsConstructor @AllArgsConstructor
public class TerminalSetInfo implements IJsonObject { public class TerminalSetInfo implements IJsonObject {
/**
* logId
*/
private Long logId;
/** /**
* 地址 * 地址
*/ */

View File

@@ -34,7 +34,6 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.utils.Valid; import org.dromara.visor.common.utils.Valid;
import org.dromara.visor.module.common.utils.SftpUtils;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps; import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.model.config.TerminalSessionSftpConfig; import org.dromara.visor.module.terminal.handler.terminal.model.config.TerminalSessionSftpConfig;
import org.dromara.visor.module.terminal.handler.terminal.model.response.SftpFileVO; import org.dromara.visor.module.terminal.handler.terminal.model.response.SftpFileVO;
@@ -117,7 +116,7 @@ public class SftpSession extends AbstractTerminalSession<ISftpTerminalSender, Te
public void move(String source, String target) { public void move(String source, String target) {
// 计算路径 // 计算路径
source = Valid.checkNormalize(source); source = Valid.checkNormalize(source);
target = SftpUtils.getAbsoluteTargetPath(source, target); target = SftpFileUtils.getAbsoluteTargetPath(source, target);
// 移动 // 移动
executor.move(source, target); executor.move(source, target);
} }

View File

@@ -40,6 +40,11 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public class TransferOperatorRequest { public class TransferOperatorRequest {
/**
* 日志id
*/
private Long logId;
/** /**
* 文件路径 * 文件路径
*/ */

View File

@@ -25,6 +25,7 @@ package org.dromara.visor.module.terminal.handler.transfer.session;
import cn.orionsec.kit.lang.define.wrapper.Ref; import cn.orionsec.kit.lang.define.wrapper.Ref;
import cn.orionsec.kit.lang.utils.Threads; import cn.orionsec.kit.lang.utils.Threads;
import cn.orionsec.kit.lang.utils.Valid; import cn.orionsec.kit.lang.utils.Valid;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.Streams; import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.net.host.SessionStore; import cn.orionsec.kit.net.host.SessionStore;
import cn.orionsec.kit.net.host.sftp.SftpFile; import cn.orionsec.kit.net.host.sftp.SftpFile;
@@ -72,7 +73,7 @@ public class DownloadSession extends TransferSession implements StreamingRespons
super.onStart(request); super.onStart(request);
log.info("DownloadSession.startDownload open start channelId: {}, path: {}", channelId, path); log.info("DownloadSession.startDownload open start channelId: {}, path: {}", channelId, path);
// 保存操作日志 // 保存操作日志
this.saveOperatorLog(TerminalOperatorType.SFTP_DOWNLOAD, path); this.saveOperatorLog(request.getLogId(), TerminalOperatorType.SFTP_DOWNLOAD, Lists.singleton(path));
// 检查连接 // 检查连接
this.init(); this.init();
// 检查文件是否存在 // 检查文件是否存在

View File

@@ -23,27 +23,24 @@
package org.dromara.visor.module.terminal.handler.transfer.session; package org.dromara.visor.module.terminal.handler.transfer.session;
import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException; import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.kit.lang.utils.io.Streams; import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.net.host.SessionStore; import cn.orionsec.kit.net.host.SessionStore;
import cn.orionsec.kit.net.host.sftp.SftpExecutor; import cn.orionsec.kit.net.host.sftp.SftpExecutor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.FieldConst; import org.dromara.visor.common.constant.FieldConst;
import org.dromara.visor.common.session.config.SshConnectConfig; import org.dromara.visor.common.session.config.SshConnectConfig;
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorLogModel; import org.dromara.visor.framework.biz.operator.log.core.model.OperatorLogModel;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.websocket.core.utils.WebSockets; import org.dromara.visor.framework.websocket.core.utils.WebSockets;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.record.TerminalAsyncSaver; import org.dromara.visor.module.terminal.handler.terminal.record.TerminalAsyncSaver;
import org.dromara.visor.module.terminal.handler.terminal.utils.TerminalUtils;
import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver; import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver;
import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorRequest; import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorRequest;
import org.dromara.visor.module.terminal.handler.transfer.utils.TransferUtils; import org.dromara.visor.module.terminal.handler.transfer.utils.TransferUtils;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map; import java.util.List;
/** /**
* 主机传输会话实现 * 主机传输会话实现
@@ -147,20 +144,16 @@ public abstract class TransferSession implements ITransferSession {
/** /**
* 保存操作日志 * 保存操作日志
* *
* @param type type * @param logId logId
* @param path path * @param type type
* @param paths paths
*/ */
protected void saveOperatorLog(String type, String path) { protected void saveOperatorLog(Long logId, String type, List<String> paths) {
// 设置参数 String path = String.join(Const.LF, paths);
Map<String, Object> extra = Maps.newMap(); int count = paths.size();
extra.put(OperatorLogs.PATH, path); // 获取操作日志
extra.put(OperatorLogs.HOST_ID, connectConfig.getHostId()); OperatorLogModel model = TransferUtils.getOperatorLogModel(type, path, count, connectConfig, WebSockets.getAttr(channel, FieldConst.PROPS));
extra.put(OperatorLogs.HOST_NAME, connectConfig.getHostName()); // 保存操作日志
extra.put(OperatorLogs.ADDRESS, connectConfig.getHostAddress());
// 获取日志
TerminalChannelProps props = WebSockets.getAttr(channel, FieldConst.PROPS);
OperatorLogModel model = TerminalUtils.getOperatorLogModel(props, extra, type, System.currentTimeMillis(), null);
// 保存
TerminalAsyncSaver.saveOperatorLog(model); TerminalAsyncSaver.saveOperatorLog(model);
} }

View File

@@ -22,6 +22,7 @@
*/ */
package org.dromara.visor.module.terminal.handler.transfer.session; package org.dromara.visor.module.terminal.handler.transfer.session;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.io.Streams; import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.net.host.SessionStore; import cn.orionsec.kit.net.host.SessionStore;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -58,7 +59,7 @@ public class UploadSession extends TransferSession {
try { try {
log.info("UploadSession.startUpload start channelId: {}, path: {}", channelId, path); log.info("UploadSession.startUpload start channelId: {}, path: {}", channelId, path);
// 保存操作日志 // 保存操作日志
this.saveOperatorLog(TerminalOperatorType.SFTP_UPLOAD, path); this.saveOperatorLog(request.getLogId(), TerminalOperatorType.SFTP_UPLOAD, Lists.singleton(path));
// 检查连接 // 检查连接
this.init(); this.init();
// 检查文件是否存在 // 检查文件是否存在

View File

@@ -23,14 +23,21 @@
package org.dromara.visor.module.terminal.handler.transfer.utils; package org.dromara.visor.module.terminal.handler.transfer.utils;
import cn.orionsec.kit.lang.utils.Strings; import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.collect.Maps;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import org.apache.catalina.connector.ClientAbortException; import org.apache.catalina.connector.ClientAbortException;
import org.dromara.visor.common.constant.ErrorMessage; import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.session.config.BaseConnectConfig;
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorLogModel;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.websocket.core.utils.WebSockets; import org.dromara.visor.framework.websocket.core.utils.WebSockets;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.utils.TerminalUtils;
import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver; import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver;
import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorResponse; import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorResponse;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@@ -45,6 +52,30 @@ public class TransferUtils {
private TransferUtils() { private TransferUtils() {
} }
/**
* 获取传输操作日志
*
* @param type type
* @param path path
* @param count count
* @param config config
* @param props props
*/
public static OperatorLogModel getOperatorLogModel(String type,
String path, Integer count,
BaseConnectConfig config,
TerminalChannelProps props) {
// 设置参数
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.COUNT, count);
extra.put(OperatorLogs.HOST_ID, config.getHostId());
extra.put(OperatorLogs.HOST_NAME, config.getHostName());
extra.put(OperatorLogs.ADDRESS, config.getHostAddress());
// 获取操作日志
return TerminalUtils.getOperatorLogModel(props, extra, type, System.currentTimeMillis(), null);
}
/** /**
* 发送消息 * 发送消息
* *

View File

@@ -22,6 +22,7 @@
*/ */
package org.dromara.visor.module.terminal.utils; package org.dromara.visor.module.terminal.utils;
import cn.orionsec.kit.lang.constant.Letters;
import cn.orionsec.kit.lang.utils.io.FileType; import cn.orionsec.kit.lang.utils.io.FileType;
import cn.orionsec.kit.lang.utils.io.Files1; import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.net.host.sftp.SftpFile; import cn.orionsec.kit.net.host.sftp.SftpFile;
@@ -41,6 +42,33 @@ public class SftpFileUtils {
private SftpFileUtils() { private SftpFileUtils() {
} }
/**
* 获取移动目标路径
*
* @param source source
* @param target target
* @return absolute target
*/
public static String getAbsoluteTargetPath(String source, String target) {
if (target.charAt(0) == Letters.SLASH) {
// 绝对路径
return Files1.getPath(Files1.normalize(target));
} else {
// 相对路径
return Files1.getPath(Files1.normalize(Files1.getPath(source + "/../" + target)));
}
}
/**
* 分割文件路径
*
* @param path path
* @return paths
*/
public static String[] fromMultiPaths(String path) {
return path.split("\\|");
}
/** /**
* 转为文件 * 转为文件
* *