From f7867a8bcbeb44d5e6a149ac0dbe924558c34a06 Mon Sep 17 00:00:00 2001 From: lijiahang Date: Tue, 2 Jan 2024 18:51:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BF=9E=E6=8E=A5=E4=B8=BB=E6=9C=BA?= =?UTF-8?q?=E7=BB=88=E7=AB=AF.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/constant/FieldConst.java | 2 + .../log/core/uitls/OperatorLogFiller.java | 23 ++++ .../operator/HostTerminalOperatorType.java | 2 +- .../entity/dto/HostTerminalConnectDTO.java | 9 ++ .../terminal/TerminalMessageDispatcher.java | 2 +- .../request/TerminalConnectRequest.java | 10 +- .../handler/AbstractTerminalHandler.java | 19 ++- .../terminal/handler/ITerminalHandler.java | 3 +- .../handler/TerminalConnectHandler.java | 121 +++++++++++++++++- .../terminal/manager/TerminalSession.java | 49 +++++++ .../TerminalAccessInterceptor.java | 2 + .../asset/service/HostTerminalService.java | 12 +- .../service/impl/HostTerminalServiceImpl.java | 14 +- 13 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/manager/TerminalSession.java diff --git a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java index 0c263403..7dbed1eb 100644 --- a/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java +++ b/orion-ops-framework/orion-ops-framework-common/src/main/java/com/orion/ops/framework/common/constant/FieldConst.java @@ -39,4 +39,6 @@ public interface FieldConst { String TARGET = "target"; + String TOKEN = "token"; + } diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/uitls/OperatorLogFiller.java b/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/uitls/OperatorLogFiller.java index 2a1a5b27..a782bc32 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/uitls/OperatorLogFiller.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/uitls/OperatorLogFiller.java @@ -9,6 +9,7 @@ import com.orion.lang.utils.Strings; import com.orion.lang.utils.json.matcher.ReplacementFormatters; import com.orion.ops.framework.biz.operator.log.core.config.OperatorLogConfig; import com.orion.ops.framework.biz.operator.log.core.enums.ReturnType; +import com.orion.ops.framework.biz.operator.log.core.factory.OperatorTypeHolder; import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel; import com.orion.ops.framework.biz.operator.log.core.model.OperatorType; import com.orion.ops.framework.common.entity.RequestIdentity; @@ -159,6 +160,17 @@ public class OperatorLogFiller implements Gettable { return this.fillResult(null, null, exception); } + /** + * 填充结果 + * + * @param ret ret + * @param exception exception + * @return this + */ + public OperatorLogFiller fillResult(Object ret, Throwable exception) { + return this.fillResult(ReturnType.JSON, ret, exception); + } + /** * 填充结果 * @@ -209,6 +221,17 @@ public class OperatorLogFiller implements Gettable { return this; } + /** + * 填充日志信息 + * + * @param extra extra + * @param type type + * @return this + */ + public OperatorLogFiller fillLogInfo(Map extra, String type) { + return this.fillLogInfo(extra, OperatorTypeHolder.get(type)); + } + /** * 填充日志信息 * diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostTerminalOperatorType.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostTerminalOperatorType.java index 802d863a..1f68109f 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostTerminalOperatorType.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/operator/HostTerminalOperatorType.java @@ -21,7 +21,7 @@ public class HostTerminalOperatorType extends InitializingOperatorTypes { @Override public OperatorType[] types() { return new OperatorType[]{ - new OperatorType(L, CONNECT, "连接主机终端 ${hostName}"), + new OperatorType(L, CONNECT, "连接主机终端 ${name}"), }; } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostTerminalConnectDTO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostTerminalConnectDTO.java index c0211fc6..3f90d004 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostTerminalConnectDTO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/dto/HostTerminalConnectDTO.java @@ -44,6 +44,15 @@ public class HostTerminalConnectDTO { @Schema(description = "超时时间") private Integer timeout; + @Schema(description = "SSH输出编码") + private String charset; + + @Schema(description = "文件名称编码") + private String fileNameCharset; + + @Schema(description = "文件内容编码") + private String fileContentCharset; + @Schema(description = "用户名") private String username; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java index d106e5ad..9670a552 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java @@ -28,7 +28,7 @@ public class TerminalMessageDispatcher extends TextWebSocketHandler { InputOperatorTypeEnum type = InputOperatorTypeEnum.of(message.getType()); if (type != null) { // 处理消息 - type.getHandler().process(session, message, payload); + type.getHandler().process(session, message); } } catch (Exception e) { log.error("TerminalDispatchHandler-handleMessage-error msg: {}", payload, e); diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java index 37017dd1..60c039f4 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java @@ -21,10 +21,16 @@ import lombok.NoArgsConstructor; @Schema(name = "TerminalConnectRequest", description = "终端连接请求 实体对象") public class TerminalConnectRequest { - // 连接主机 {"t":"co","s": "1001","b":{"h":1}} + // 连接主机 {"t":"co","s": "1001","b":{"h":1,"cols":100,"rows":20}} @JSONField(name = "h") @Schema(description = "主机id") - private String hostId; + private Long hostId; + + @Schema(description = "列数") + private Integer cols; + + @Schema(description = "行数") + private Integer rows; } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java index 0e1831c5..7c838d74 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java @@ -24,10 +24,10 @@ public abstract class AbstractTerminalHandler implements ITerminalHandler { @Override @SuppressWarnings("unchecked") - public void process(WebSocketSession session, Message message, String payload) { + public void process(WebSocketSession session, Message message) { Message res = (Message) message; res.setBody(((JSONObject) message.getBody()).toJavaObject(convert)); - this.onMessage(session, res); + this.handle(session, res); } /** @@ -36,6 +36,19 @@ public abstract class AbstractTerminalHandler implements ITerminalHandler { * @param session session * @param msg msg */ - protected abstract void onMessage(WebSocketSession session, Message msg); + protected abstract void handle(WebSocketSession session, Message msg); + + /** + * 获取属性 + * + * @param session session + * @param attr attr + * @param T + * @return T + */ + @SuppressWarnings("unchecked") + protected T getAttr(WebSocketSession session, String attr) { + return (T) session.getAttributes().get(attr); + } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java index f5ac554d..a280d418 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java @@ -17,8 +17,7 @@ public interface ITerminalHandler { * * @param session session * @param message message - * @param payload payload */ - void process(WebSocketSession session, Message message, String payload); + void process(WebSocketSession session, Message message); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java index aa6b2932..0d96aef3 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java @@ -1,10 +1,29 @@ package com.orion.ops.module.asset.handler.host.terminal.handler; +import com.orion.lang.utils.collect.Maps; +import com.orion.net.host.SessionStore; +import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService; +import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogFiller; +import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; +import com.orion.ops.framework.common.constant.ExtraFieldConst; +import com.orion.ops.module.asset.dao.HostDAO; +import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType; +import com.orion.ops.module.asset.entity.domain.HostDO; +import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; +import com.orion.ops.module.asset.entity.request.host.HostConnectLogCreateRequest; +import com.orion.ops.module.asset.enums.HostConnectTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.entity.Message; import com.orion.ops.module.asset.handler.host.terminal.entity.request.TerminalConnectRequest; +import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalSession; +import com.orion.ops.module.asset.service.HostConnectLogService; +import com.orion.ops.module.asset.service.HostTerminalService; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; +import javax.annotation.Resource; +import java.util.Map; + /** * 连接主机处理器 * @@ -12,16 +31,114 @@ import org.springframework.web.socket.WebSocketSession; * @version 1.0.0 * @since 2023/12/29 15:32 */ +@Slf4j @Component public class TerminalConnectHandler extends AbstractTerminalHandler { + @Resource + private HostDAO hostDAO; + + @Resource + private HostTerminalService hostTerminalService; + + @Resource + private HostConnectLogService hostConnectLogService; + + @Resource + private OperatorLogFrameworkService operatorLogFrameworkService; + public TerminalConnectHandler() { super(TerminalConnectRequest.class); } @Override - protected void onMessage(WebSocketSession session, Message msg) { - System.out.println(msg); + protected void handle(WebSocketSession session, Message msg) { + TerminalConnectRequest body = msg.getBody(); + Long hostId = body.getHostId(); + Long userId = this.getAttr(session, ExtraFieldConst.USER_ID); + log.info("TerminalConnectHandler-handle start userId: {}, hostId: {}", userId, hostId); + // 查询主机信息 + HostDO host = hostDAO.selectById(hostId); + if (host == null) { + // TODO 不存在返回错误信息 + + return; + } + // 日志信息 + long startTime = System.currentTimeMillis(); + Exception ex = null; + String terminalToken = null; + try { + // 连接主机 + HostTerminalConnectDTO connect = hostTerminalService.getTerminalConnectInfo(userId, host); + terminalToken = connect.getToken(); + SessionStore sessionStore = hostTerminalService.openSessionStore(connect); + TerminalSession terminalSession = new TerminalSession(session, connect, sessionStore); + terminalSession.connect(body.getCols(), body.getRows()); + log.info("TerminalConnectHandler-handle success userId: {}, hostId: {}", userId, hostId); + // TODO 添加到 manager + + } catch (Exception e) { + log.error("TerminalConnectHandler-handle error userId: {}, hostId: {}", userId, hostId, e); + ex = e; + } finally { + // 记录主机日志 + this.saveTerminalLog(session, userId, host, startTime, ex, terminalToken); + } + } + + /** + * 记录主机日志 + * + * @param session session + * @param userId userId + * @param host host + * @param startTime startTime + * @param ex ex + * @param terminalToken terminalToken + */ + private void saveTerminalLog(WebSocketSession session, + Long userId, + HostDO host, + long startTime, + Exception ex, + String terminalToken) { + Long hostId = host.getId(); + String hostName = host.getName(); + String username = this.getAttr(session, ExtraFieldConst.USERNAME); + // 额外参数 + Map extra = Maps.newMap(); + extra.put(OperatorLogs.ID, hostId); + extra.put(OperatorLogs.NAME, hostName); + extra.put(OperatorLogs.TOKEN, terminalToken); + // 日志参数 + OperatorLogFiller logModel = OperatorLogFiller.create() + // 填充用户信息 + .fillUserInfo(userId, username) + // 填充 traceId + .fillTraceId(this.getAttr(session, ExtraFieldConst.TRACE_ID)) + // 填充请求留痕信息 + .fillIdentity(this.getAttr(session, ExtraFieldConst.IDENTITY)) + // 填充使用时间 + .fillUsedTime(startTime) + // 填充结果信息 + .fillResult(null, ex) + // 填充拓展信息 + .fillExtra(extra) + // 填充日志 + .fillLogInfo(extra, HostTerminalOperatorType.CONNECT); + // 记录操作日志 + operatorLogFrameworkService.insert(logModel.get()); + // 记录连接日志 + HostConnectLogCreateRequest connectLog = HostConnectLogCreateRequest.builder() + .userId(userId) + .username(username) + .hostId(hostId) + .hostName(hostName) + .hostAddress(host.getAddress()) + .token(terminalToken) + .build(); + hostConnectLogService.create(HostConnectTypeEnum.SSH, connectLog); } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/manager/TerminalSession.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/manager/TerminalSession.java new file mode 100644 index 00000000..1c7def02 --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/manager/TerminalSession.java @@ -0,0 +1,49 @@ +package com.orion.ops.module.asset.handler.host.terminal.manager; + +import com.orion.lang.able.SafeCloseable; +import com.orion.net.host.SessionStore; +import com.orion.net.host.ssh.shell.ShellExecutor; +import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; +import org.springframework.web.socket.WebSocketSession; + +/** + * 终端会话 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/1/2 17:28 + */ +public class TerminalSession implements SafeCloseable { + + private final WebSocketSession session; + + private final HostTerminalConnectDTO connect; + + private final SessionStore sessionStore; + + private ShellExecutor executor; + + public TerminalSession(WebSocketSession session, + HostTerminalConnectDTO connect, + SessionStore sessionStore) { + this.session = session; + this.connect = connect; + this.sessionStore = sessionStore; + } + + /** + * 连接 + * + * @param cols cols + * @param rows rows + */ + public void connect(int cols, int rows) { + this.executor = sessionStore.getShellExecutor(); + executor.size(cols, rows); + } + + @Override + public void close() { + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/interceptor/TerminalAccessInterceptor.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/interceptor/TerminalAccessInterceptor.java index 50224e03..963c50d6 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/interceptor/TerminalAccessInterceptor.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/interceptor/TerminalAccessInterceptor.java @@ -35,6 +35,7 @@ public class TerminalAccessInterceptor implements HandshakeInterceptor { String token = Urls.getUrlSource(request.getURI().getPath()); log.info("TerminalInterceptor-beforeHandshake start token: {}", token); attributes.put(ExtraFieldConst.USER_ID, 1L); + attributes.put(ExtraFieldConst.USERNAME, "1"); attributes.put(ExtraFieldConst.TRACE_ID, TraceIdHolder.get()); attributes.put(ExtraFieldConst.IDENTITY, Requests.getIdentity()); // 获取连接数据 @@ -45,6 +46,7 @@ public class TerminalAccessInterceptor implements HandshakeInterceptor { // } // // 设置参数 // attributes.put(ExtraFieldConst.USER_ID, access.getUserId()); + // attributes.put(ExtraFieldConst.USERNAME, access.getUsername()); // attributes.put(ExtraFieldConst.TRACE_ID, TraceIdHolder.get()); // attributes.put(ExtraFieldConst.IDENTITY, Requests.getIdentity()); return true; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/HostTerminalService.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/HostTerminalService.java index a0afe31d..a57a8628 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/HostTerminalService.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/HostTerminalService.java @@ -1,6 +1,7 @@ package com.orion.ops.module.asset.service; import com.orion.net.host.SessionStore; +import com.orion.ops.module.asset.entity.domain.HostDO; import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; @@ -30,7 +31,7 @@ public interface HostTerminalService { HostTerminalAccessDTO getAccessInfoByToken(String token); /** - * 使用用户配置打开获取连接信息 + * 使用用户配置获取连接信息 * * @param hostId hostId * @param userId userId @@ -38,6 +39,15 @@ public interface HostTerminalService { */ HostTerminalConnectDTO getTerminalConnectInfo(Long userId, Long hostId); + /** + * 使用用户配置获取连接信息 + * + * @param host host + * @param userId userId + * @return session + */ + HostTerminalConnectDTO getTerminalConnectInfo(Long userId, HostDO host); + /** * 使用默认配置打开主机会话 * diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostTerminalServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostTerminalServiceImpl.java index 1dfe0c80..782cdbb2 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostTerminalServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/HostTerminalServiceImpl.java @@ -82,7 +82,7 @@ public class HostTerminalServiceImpl implements HostTerminalService { @Override public String getHostTerminalAccessToken(Long userId) { log.info("HostConnectService.getHostAccessToken userId: {}", userId); - String token = UUIds.random19(); + String token = UUIds.random32(); HostTerminalAccessDTO access = HostTerminalAccessDTO.builder() .token(token) .userId(userId) @@ -107,10 +107,16 @@ public class HostTerminalServiceImpl implements HostTerminalService { @Override public HostTerminalConnectDTO getTerminalConnectInfo(Long userId, Long hostId) { - log.info("HostConnectService.getTerminalConnectInfo hostId: {}, userId: {}", hostId, userId); // 查询主机 HostDO host = hostDAO.selectById(hostId); Valid.notNull(host, ErrorMessage.HOST_ABSENT); + return this.getTerminalConnectInfo(userId, host); + } + + @Override + public HostTerminalConnectDTO getTerminalConnectInfo(Long userId, HostDO host) { + Long hostId = host.getId(); + log.info("HostConnectService.getTerminalConnectInfo hostId: {}, userId: {}", hostId, userId); // 查询用户 SystemUserDTO user = systemUserApi.getUserById(userId); Valid.notNull(user, ErrorMessage.USER_ABSENT); @@ -143,6 +149,7 @@ public class HostTerminalServiceImpl implements HostTerminalService { } } // 获取连接配置 + // TODO 看看需不需要 不需要的话就修改位置 HostTerminalConnectDTO connect = this.getHostConnectInfo(host, config, extra); connect.setUserId(userId); connect.setToken(UUIds.random15()); @@ -251,6 +258,9 @@ public class HostTerminalServiceImpl implements HostTerminalService { conn.setHostName(host.getName()); conn.setHostAddress(host.getAddress()); conn.setPort(config.getPort()); + conn.setCharset(config.getCharset()); + conn.setFileNameCharset(config.getFileNameCharset()); + conn.setFileContentCharset(config.getFileContentCharset()); conn.setTimeout(config.getConnectTimeout()); conn.setUsername(config.getUsername()); // 填充身份信息