🔨 优化 sftp 代码逻辑.

This commit is contained in:
lijiahang
2024-02-19 17:32:20 +08:00
parent 104090887e
commit 4117fb3ffa
15 changed files with 163 additions and 54 deletions

View File

@@ -77,4 +77,6 @@ public interface ErrorMessage {
String CONNECT_ERROR = "连接失败";
String PATH_NOT_NORMALIZE = "路径不合法";
}

View File

@@ -1,6 +1,7 @@
package com.orion.ops.framework.common.utils;
import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.io.Files1;
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.spring.SpringHolder;
@@ -116,4 +117,15 @@ public class Valid extends com.orion.lang.utils.Valid {
return effect;
}
/**
* 检查路径是否合法化 即不包含 ./ ../
*
* @param path path
*/
public static String checkNormalize(String path) {
Valid.notBlank(path);
Valid.isTrue(Files1.isNormalize(path), ErrorMessage.PATH_NOT_NORMALIZE);
return Files1.getPath(path);
}
}

View File

@@ -2,9 +2,12 @@ package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.ops.framework.websocket.core.utils.WebSockets;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/**
* 终端消息处理器 基类
*
@@ -14,6 +17,9 @@ import org.springframework.web.socket.WebSocketSession;
*/
public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> implements ITerminalHandler<T> {
@Resource
protected TerminalManager terminalManager;
/**
* 发送消息
*

View File

@@ -1,15 +1,11 @@
package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SshInputRequest;
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/**
* ssh 处理输入处理器
*
@@ -21,17 +17,12 @@ import javax.annotation.Resource;
@Component
public class SshInputHandler extends AbstractTerminalHandler<SshInputRequest> {
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, SshInputRequest payload) {
// 获取会话
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
if (session instanceof ISshSession) {
// 处理输入
((ISshSession) session).write(payload.getCommand());
}
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
// 处理输入
session.write(payload.getCommand());
}
}

View File

@@ -1,15 +1,11 @@
package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.request.SshResizeRequest;
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/**
* ssh 修改大小处理器
*
@@ -21,17 +17,12 @@ import javax.annotation.Resource;
@Component
public class SshResizeHandler extends AbstractTerminalHandler<SshResizeRequest> {
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, SshResizeRequest payload) {
// 获取会话
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
if (session instanceof ISshSession) {
// 修改大小
((ISshSession) session).resize(payload.getCols(), payload.getRows());
}
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
// 修改大小
session.resize(payload.getCols(), payload.getRows());
}
}

View File

@@ -17,7 +17,6 @@ import com.orion.ops.module.asset.entity.request.host.HostConnectLogCreateReques
import com.orion.ops.module.asset.enums.HostConnectStatusEnum;
import com.orion.ops.module.asset.enums.HostConnectTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCheckResponse;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
@@ -53,9 +52,6 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
@Resource
private OperatorLogFrameworkService operatorLogFrameworkService;
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, TerminalCheckRequest payload) {
Long hostId = payload.getHostId();

View File

@@ -1,13 +1,10 @@
package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/**
* 关闭处理器
*
@@ -19,9 +16,6 @@ import javax.annotation.Resource;
@Component
public class TerminalCloseHandler extends AbstractTerminalHandler<TerminalBasePayload> {
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
log.info("TerminalCloseHandler-handle start session: {}", payload.getSessionId());

View File

@@ -14,7 +14,6 @@ import com.orion.ops.module.asset.enums.HostConnectStatusEnum;
import com.orion.ops.module.asset.enums.HostConnectTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.constant.TerminalMessage;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalConnectRequest;
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalConnectResponse;
@@ -46,9 +45,6 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
@Resource
private HostConnectLogService hostConnectLogService;
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, TerminalConnectRequest payload) {
String sessionId = payload.getSessionId();

View File

@@ -2,14 +2,12 @@ package com.orion.ops.module.asset.handler.host.terminal.handler;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
import java.util.Map;
/**
@@ -23,9 +21,6 @@ import java.util.Map;
@Component
public class TerminalPingHandler extends AbstractTerminalHandler<TerminalBasePayload> {
@Resource
private TerminalManager terminalManager;
@Override
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
// 发送 pong

View File

@@ -52,10 +52,12 @@ public class TerminalManager {
*
* @param channelId channelId
* @param sessionId sessionId
* @param T T
* @return session
*/
public ITerminalSession getSession(String channelId, String sessionId) {
return channelSessions.get(channelId, sessionId);
@SuppressWarnings("unchecked")
public <T extends ITerminalSession> T getSession(String channelId, String sessionId) {
return (T) channelSessions.get(channelId, sessionId);
}
/**

View File

@@ -28,7 +28,7 @@ public class SftpChangeModRequest extends TerminalBasePayload {
@Schema(description = "path")
private String path;
@Schema(description = "权限")
private String mod;
@Schema(description = "10进制的8进制 权限")
private Integer mod;
}

View File

@@ -8,10 +8,12 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
/**
* sftp 删除文件 实体对象
* <p>
* i|eff00a1|path
* i|eff00a1|paths
*
* @author Jiahang Li
* @version 1.0.0
@@ -25,7 +27,7 @@ import lombok.experimental.SuperBuilder;
@Schema(name = "SftpRemoveRequest", description = "sftp 删除文件 实体对象")
public class SftpRemoveRequest extends TerminalBasePayload {
@Schema(description = "path")
private String path;
@Schema(description = "paths 多个用|分割")
private List<String> paths;
}

View File

@@ -23,12 +23,12 @@ import lombok.experimental.SuperBuilder;
@Schema(name = "SftpListResponse", description = "sftp 列表响应 实体对象")
public class SftpListResponse extends TerminalBasePayload {
@Schema(description = "检查结果")
private Integer result;
@Schema(description = "path")
private String path;
@Schema(description = "结果")
private Integer result;
@Schema(description = "body")
private String body;

View File

@@ -34,4 +34,64 @@ public interface ISftpSession extends ITerminalSession {
*/
List<SftpFileResponse> list(String path, boolean showHiddenFile);
/**
* 创建文件夹
*
* @param path path
*/
void mkdir(String path);
/**
* 创建文件
*
* @param path path
*/
void touch(String path);
/**
* 移动文件
*
* @param source source
* @param target target
*/
void move(String source, String target);
/**
* 删除文件
*
* @param paths paths
*/
void remove(List<String> paths);
/**
* 截断文件
*
* @param path path
*/
void truncate(String path);
/**
* 修改权限
*
* @param path path
* @param mod mod
*/
void chmod(String path, int mod);
/**
* 获取内容
*
* @param path path
* @return content
*/
String getContent(String path);
/**
* 设置内容
*
* @param path path
* @param content content
*/
void setContent(String path, String content);
}

View File

@@ -1,5 +1,7 @@
package com.orion.ops.module.asset.handler.host.terminal.session;
import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.io.FileType;
import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.io.Streams;
@@ -7,17 +9,19 @@ import com.orion.net.host.SessionStore;
import com.orion.net.host.sftp.SftpExecutor;
import com.orion.net.host.sftp.SftpFile;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpFileResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 终端 ssh 会话
* 终端 sftp 会话
*
* @author Jiahang Li
* @version 1.0.0
@@ -55,6 +59,7 @@ public class SftpSession extends TerminalSession implements ISftpSession {
@Override
public List<SftpFileResponse> list(String path, boolean showHiddenFile) {
path = Files1.getPath(path);
// 查询文件
List<SftpFile> files = executor.listFilesFilter(path,
s -> showHiddenFile || !s.getName().startsWith(Const.DOT),
@@ -65,6 +70,63 @@ public class SftpSession extends TerminalSession implements ISftpSession {
.collect(Collectors.toList());
}
@Override
public void mkdir(String path) {
path = Valid.checkNormalize(path);
executor.makeDirectories(path);
}
@Override
public void touch(String path) {
path = Valid.checkNormalize(path);
executor.touch(path);
}
@Override
public void move(String source, String target) {
source = Valid.checkNormalize(source);
executor.move(source, target);
}
@Override
public void remove(List<String> paths) {
paths.stream()
.map(Valid::checkNormalize)
.forEach(executor::remove);
}
@Override
public void truncate(String path) {
path = Valid.checkNormalize(path);
executor.truncate(path);
}
@Override
public void chmod(String path, int mod) {
path = Valid.checkNormalize(path);
executor.changeMode(path, mod);
}
@Override
public String getContent(String path) {
path = Valid.checkNormalize(path);
try (InputStream in = executor.openInputStream(path)) {
return Streams.toString(in, config.getFileContentCharset());
} catch (Exception e) {
throw Exceptions.ioRuntime(e);
}
}
@Override
public void setContent(String path, String content) {
path = Valid.checkNormalize(path);
try {
executor.write(path, Strings.bytes(content, config.getFileContentCharset()));
} catch (Exception e) {
throw Exceptions.ioRuntime(e);
}
}
@Override
public void keepAlive() {
try {