机器连接相关代码(注释掉)

This commit is contained in:
唐潇凯 2025-07-03 10:51:32 +08:00
parent 242c9e282b
commit 28ed6b5c92
9 changed files with 575 additions and 574 deletions

View File

@ -1,230 +1,230 @@
package cd.casic.module.machine.component; //package cd.casic.module.machine.component;
//
import cd.casic.framework.commons.exception.ServiceException; //import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO; //import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.enums.AuthenticationType; //import cd.casic.module.machine.enums.AuthenticationType;
import cd.casic.module.machine.enums.ConnectionStatus; //import cd.casic.module.machine.enums.ConnectionStatus;
import cd.casic.module.machine.enums.SSHChanelType; //import cd.casic.module.machine.enums.SSHChanelType;
import cd.casic.module.machine.service.SecretKeyService; //import cd.casic.module.machine.service.SecretKeyService;
import com.jcraft.jsch.Channel; //import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec; //import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch; //import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException; //import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session; //import com.jcraft.jsch.Session;
import lombok.Data; //import lombok.Data;
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; //import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage; //import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; //import org.springframework.web.socket.WebSocketSession;
//
import java.io.BufferedReader; //import java.io.BufferedReader;
import java.io.IOException; //import java.io.IOException;
import java.io.InputStream; //import java.io.InputStream;
import java.io.InputStreamReader; //import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; //import java.nio.charset.StandardCharsets;
import java.util.Properties; //import java.util.Properties;
//
import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; //import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
import static cd.casic.module.machine.contants.MachineErrorCodeConstants.SECRET_KEY_NULL; //import static cd.casic.module.machine.contants.MachineErrorCodeConstants.SECRET_KEY_NULL;
import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; //import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
//
@Slf4j //@Slf4j
@Data //@Data
@Component //@Component
public class WebSocketConnection { //public class WebSocketConnection {
private SecretKeyService secretKeyService; // private SecretKeyService secretKeyService;
//
private MachineInfoDO machineInfo; // private MachineInfoDO machineInfo;
private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED; // private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED;
private Session sshSession; // private Session sshSession;
//
public WebSocketConnection(SecretKeyService secretKeyService) { // public WebSocketConnection(SecretKeyService secretKeyService) {
this.secretKeyService = secretKeyService; // this.secretKeyService = secretKeyService;
} // }
//
private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒) // private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒)
//
public void initConnection(MachineInfoDO machineInfo) { // public void initConnection(MachineInfoDO machineInfo) {
try { // try {
this.machineInfo = machineInfo; // this.machineInfo = machineInfo;
this.sshSession = doConnect(machineInfo); // this.sshSession = doConnect(machineInfo);
log.info("已成功建立 SSH 连接至 {} ", machineInfo.getHostIp()); // log.info("已成功建立 SSH 连接至 {} ", machineInfo.getHostIp());
this.connectionStatus = ConnectionStatus.CONNECTING; // this.connectionStatus = ConnectionStatus.CONNECTING;
} catch (ServiceException e) { // } catch (ServiceException e) {
log.warn("SSH 连接失败: {}", e.getMessage()); // log.warn("SSH 连接失败: {}", e.getMessage());
throw e; // throw e;
} // }
} // }
//
public void disconnect() { // public void disconnect() {
if (sshSession != null && sshSession.isConnected()) { // if (sshSession != null && sshSession.isConnected()) {
try { // try {
sshSession.disconnect(); // sshSession.disconnect();
log.info("SSH连接关闭: {}", machineInfo.getHostIp()); // log.info("SSH连接关闭: {}", machineInfo.getHostIp());
} catch (Exception e) { // } catch (Exception e) {
log.error("关闭SSH连接失败: {}", e.getMessage()); // log.error("关闭SSH连接失败: {}", e.getMessage());
throw exception(CLOSE_CLOSE_SESSION_ERROR); // throw exception(CLOSE_CLOSE_SESSION_ERROR);
} // }
} // }
connectionStatus = ConnectionStatus.DISCONNECTED; // connectionStatus = ConnectionStatus.DISCONNECTED;
} // }
//
/** // /**
* 执行远程命令支持超时和中断处理 // * 执行远程命令支持超时和中断处理
*/ // */
public void executeCommand(WebSocketSession webSocketSession, String command) { // public void executeCommand(WebSocketSession webSocketSession, String command) {
// 1. 检查连接状态 // // 1. 检查连接状态
if (sshSession == null || !sshSession.isConnected()) { // if (sshSession == null || !sshSession.isConnected()) {
sendErrorMessage(webSocketSession, "SSH连接未建立或已断开"); // sendErrorMessage(webSocketSession, "SSH连接未建立或已断开");
return; // return;
} // }
try { // try {
// 2. 创建SSH命令执行通道 // // 2. 创建SSH命令执行通道
Channel channel; // Channel channel;
try { // try {
channel = sshSession.openChannel(SSHChanelType.EXEC.getMessage()); // channel = sshSession.openChannel(SSHChanelType.EXEC.getMessage());
} catch (JSchException e) { // } catch (JSchException e) {
throw exception(CREATE_CHANEL_ERROR); // throw exception(CREATE_CHANEL_ERROR);
} // }
((ChannelExec) channel).setCommand(command); // ((ChannelExec) channel).setCommand(command);
// 3. 设置输入/输出流 // // 3. 设置输入/输出流
channel.setInputStream(null); // channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err); // ((ChannelExec) channel).setErrStream(System.err);
// 4. 获取命令输出流 // // 4. 获取命令输出流
InputStream inputStream = channel.getInputStream(); // InputStream inputStream = channel.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); // InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(inputStreamReader); // BufferedReader reader = new BufferedReader(inputStreamReader);
// 5. 连接并执行命令 // // 5. 连接并执行命令
channel.connect(); // channel.connect();
// 6. 读取命令输出并实时发送给客户端 // // 6. 读取命令输出并实时发送给客户端
String line; // String line;
while ((line = reader.readLine()) != null) { // while ((line = reader.readLine()) != null) {
// 实时发送输出到客户端 // // 实时发送输出到客户端
webSocketSession.sendMessage(new TextMessage(line)); // webSocketSession.sendMessage(new TextMessage(line));
} // }
// 7. 等待命令执行完成 // // 7. 等待命令执行完成
int exitStatus = channel.getExitStatus(); // int exitStatus = channel.getExitStatus();
// 8. 发送命令执行完毕的消息 // // 8. 发送命令执行完毕的消息
webSocketSession.sendMessage(new TextMessage( // webSocketSession.sendMessage(new TextMessage(
"[系统] 命令执行完毕,退出状态: " + exitStatus // "[系统] 命令执行完毕,退出状态: " + exitStatus
)); // ));
// 9. 关闭通道 // // 9. 关闭通道
channel.disconnect(); // channel.disconnect();
} catch (JSchException | IOException e) { // } catch (JSchException | IOException e) {
throw exception(EXECUTE_COMMAND_FAIL); // throw exception(EXECUTE_COMMAND_FAIL);
} // }
} // }
//
// 发送错误消息的辅助方法 // // 发送错误消息的辅助方法
public void sendErrorMessage(WebSocketSession webSocketSession, String message) { // public void sendErrorMessage(WebSocketSession webSocketSession, String message) {
try { // try {
if (webSocketSession.isOpen()) { // if (webSocketSession.isOpen()) {
webSocketSession.sendMessage(new TextMessage("[错误] " + message)); // webSocketSession.sendMessage(new TextMessage("[错误] " + message));
} // }
} catch (IOException e) { // } catch (IOException e) {
log.error("发送错误消息失败", e); // log.error("发送错误消息失败", e);
throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); // throw exception(WEBSOCKET_SEND_MESSAGE_ERROR);
} // }
} // }
//
/** // /**
* 实际执行连接逻辑 // * 实际执行连接逻辑
*/ // */
private Session doConnect(MachineInfoDO machineInfo) { // private Session doConnect(MachineInfoDO machineInfo) {
JSch jsch = new JSch(); // JSch jsch = new JSch();
// 配置认证方式 // // 配置认证方式
configureAuthentication(jsch, machineInfo); // configureAuthentication(jsch, machineInfo);
Session session; // Session session;
// 创建SSH会话 // // 创建SSH会话
try { // try {
session = jsch.getSession( // session = jsch.getSession(
machineInfo.getUsername(), // machineInfo.getUsername(),
machineInfo.getHostIp(), // machineInfo.getHostIp(),
machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22 // machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22
); // );
} catch (JSchException e) { // } catch (JSchException e) {
throw exception(CREATE_SESSION_ERROR); // throw exception(CREATE_SESSION_ERROR);
} // }
// 配置连接参数 // // 配置连接参数
configureSession(session, machineInfo); // configureSession(session, machineInfo);
// 建立连接 // // 建立连接
try { // try {
session.connect(CONNECTION_TIMEOUT); // session.connect(CONNECTION_TIMEOUT);
} catch (JSchException e) { // } catch (JSchException e) {
throw exception(SESSION_CONNECT_ERROR); // throw exception(SESSION_CONNECT_ERROR);
} // }
return session; // return session;
} // }
//
/** //// /**
* 配置认证方式密码或密钥 //// * 配置认证方式密码或密钥
*/ //// */
private void configureAuthentication(JSch jsch, MachineInfoDO machineInfo) { //// private void configureAuthentication(JSch jsch, MachineInfoDO machineInfo) {
if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY.getCode()) { //// if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY.getCode()) {
// 密钥认证 //// // 密钥认证
if (machineInfo.getSecretKeyId() == null) { //// if (machineInfo.getSecretKeyId() == null) {
throw exception(SECRET_KEY_NULL); //// throw exception(SECRET_KEY_NULL);
} //// }
String pubKeyContent = secretKeyService.getKeyContent(machineInfo.getSecretKeyId()); //// String pubKeyContent = secretKeyService.getKeyContent(machineInfo.getSecretKeyId());
// 验证秘钥格式 //// // 验证秘钥格式
if (!pubKeyContent.startsWith("-----BEGIN")) { //// if (!pubKeyContent.startsWith("-----BEGIN")) {
log.error("无效的密钥格式{}", pubKeyContent); //// log.error("无效的密钥格式{}", pubKeyContent);
throw exception(INVALID_kEY_FORMAT); //// throw exception(INVALID_kEY_FORMAT);
} //// }
try { //// try {
// 尝试加载秘钥私钥 //// // 尝试加载秘钥私钥
jsch.addIdentity( //// jsch.addIdentity(
machineInfo.getName(), //// machineInfo.getName(),
pubKeyContent.getBytes(StandardCharsets.UTF_8), //// pubKeyContent.getBytes(StandardCharsets.UTF_8),
null, //// null,
null //// null
); //// );
log.info("密钥加载成功 {}", machineInfo.getHostIp()); //// log.info("密钥加载成功 {}", machineInfo.getHostIp());
} catch (JSchException e) { //// } catch (JSchException e) {
log.error("密钥加载失败: {}", e.getMessage()); //// log.error("密钥加载失败: {}", e.getMessage());
throw exception(READ_SECRET_CONTENT_ERROR); //// throw exception(READ_SECRET_CONTENT_ERROR);
} //// }
} else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD.getCode()) { //// } else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD.getCode()) {
// 密码认证 //// // 密码认证
if (!StringUtils.hasText(machineInfo.getPassword())) { //// if (!StringUtils.hasText(machineInfo.getPassword())) {
throw exception(PASSWORD_NOT_EXISTS); //// throw exception(PASSWORD_NOT_EXISTS);
} //// }
} else { //// } else {
log.error("不支持该验证类型:{}", machineInfo.getAuthenticationType()); //// log.error("不支持该验证类型:{}", machineInfo.getAuthenticationType());
throw exception(NOT_SUPPORT_AUTHENTICATION_TYPE); //// throw exception(NOT_SUPPORT_AUTHENTICATION_TYPE);
} //// }
} //// }
//
/** // /**
* 配置SSH会话参数安全增强 // * 配置SSH会话参数安全增强
*/ // */
private void configureSession(Session session, MachineInfoDO machineInfo) { // private void configureSession(Session session, MachineInfoDO machineInfo) {
Properties config = new Properties(); // Properties config = new Properties();
// 根据认证类型配置不同的认证策略 // // 根据认证类型配置不同的认证策略
if (machineInfo.getAuthenticationType() == 1) { // 密码认证 // if (machineInfo.getAuthenticationType() == 1) { // 密码认证
// 设置密码 // // 设置密码
session.setPassword(machineInfo.getPassword()); // session.setPassword(machineInfo.getPassword());
config.put("StrictHostKeyChecking", "no"); // config.put("StrictHostKeyChecking", "no");
// 仅使用密码认证禁用其他认证方式 // // 仅使用密码认证禁用其他认证方式
config.put("PreferredAuthentications", "password"); // config.put("PreferredAuthentications", "password");
// 禁用公钥相关配置避免干扰 // // 禁用公钥相关配置避免干扰
config.put("PubkeyAuthentication", "no"); // config.put("PubkeyAuthentication", "no");
} else { // 密钥认证 // } else { // 密钥认证
try { // try {
String preKeyPath = secretKeyService.getSecretKey(machineInfo.getSecretKeyId()).getPath(); // String preKeyPath = secretKeyService.getSecretKey(machineInfo.getSecretKeyId()).getPath();
JSch jsch = new JSch(); // JSch jsch = new JSch();
jsch.addIdentity(preKeyPath); // 添加私钥 // jsch.addIdentity(preKeyPath); // 添加私钥
// 保持默认认证顺序公钥优先 // // 保持默认认证顺序公钥优先
config.put("PreferredAuthentications", "publicKey,password,keyboard-interactive"); // config.put("PreferredAuthentications", "publicKey,password,keyboard-interactive");
} catch (JSchException e) { // } catch (JSchException e) {
log.error("SSH密钥配置失败", e); // log.error("SSH密钥配置失败", e);
throw exception(SSH_KEY_CONFIGURATION_FAIL); // throw exception(SSH_KEY_CONFIGURATION_FAIL);
} // }
} // }
config.put("ServerAliveInterval", "30"); // 每30秒发送一次心跳 // config.put("ServerAliveInterval", "30"); // 每30秒发送一次心跳
config.put("ServerAliveCountMax", "3"); // 允许3次心跳失败 // config.put("ServerAliveCountMax", "3"); // 允许3次心跳失败
session.setConfig(config); // session.setConfig(config);
} // }
//
} //}

View File

@ -1,114 +1,114 @@
package cd.casic.module.machine.component; //package cd.casic.module.machine.component;
//
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; //import org.springframework.web.socket.WebSocketSession;
//
import java.util.Collection; //import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap; //import java.util.concurrent.ConcurrentHashMap;
//
@Component("machineWebSocketSessionManger") //@Component("machineWebSocketSessionManger")
//管理webSocketSession ////管理webSocketSession
public class WebSocketSessionManager { //public class WebSocketSessionManager {
//
//webSocketSessionId - WebSocketSession 保存 WebSocketSession 对象与会话 ID 的映射 // //webSocketSessionId - WebSocketSession 保存 WebSocketSession 对象与会话 ID 的映射
private static final ConcurrentHashMap<String, WebSocketSession> WebSocketSessionMap = new ConcurrentHashMap<>(); // private static final ConcurrentHashMap<String, WebSocketSession> WebSocketSessionMap = new ConcurrentHashMap<>();
//
//webSocketSessionId - WebSocketConnection 与远程机器的会话管理 // //webSocketSessionId - WebSocketConnection 与远程机器的会话管理
private static final ConcurrentHashMap<String, WebSocketConnection> sessionConnectionMap = new ConcurrentHashMap<>(); // private static final ConcurrentHashMap<String, WebSocketConnection> sessionConnectionMap = new ConcurrentHashMap<>();
//
//机器id - WebSocketConnection // //机器id - WebSocketConnection
private static final ConcurrentHashMap<Long, WebSocketConnection> webSocketSessionConnectionMap = new ConcurrentHashMap<>(); // private static final ConcurrentHashMap<Long, WebSocketConnection> webSocketSessionConnectionMap = new ConcurrentHashMap<>();
//
public static void addWebSocketSession(String sessionId, WebSocketSession session) { // public static void addWebSocketSession(String sessionId, WebSocketSession session) {
WebSocketSessionMap.put(sessionId, session); // WebSocketSessionMap.put(sessionId, session);
} // }
//
/** // /**
* 获取 WebSocketSession // * 获取 WebSocketSession
*/ // */
public static WebSocketSession getWebSocketSession(String sessionId) { // public static WebSocketSession getWebSocketSession(String sessionId) {
return WebSocketSessionMap.get(sessionId); // return WebSocketSessionMap.get(sessionId);
} // }
//
/** // /**
* 移除 WebSocketSession // * 移除 WebSocketSession
*/ // */
public static void removeWebSocketSession(String sessionId) { // public static void removeWebSocketSession(String sessionId) {
WebSocketSessionMap.remove(sessionId); // WebSocketSessionMap.remove(sessionId);
} // }
//
/** // /**
* 检查 sessionId 是否存在 // * 检查 sessionId 是否存在
*/ // */
public static boolean containsWebSocketSession(String sessionId) { // public static boolean containsWebSocketSession(String sessionId) {
return WebSocketSessionMap.containsKey(sessionId); // return WebSocketSessionMap.containsKey(sessionId);
} // }
//
/** // /**
* 获取所有 WebSocketSession // * 获取所有 WebSocketSession
*/ // */
public static Collection<WebSocketSession> getAllWebSocketSessions() { // public static Collection<WebSocketSession> getAllWebSocketSessions() {
return WebSocketSessionMap.values(); // return WebSocketSessionMap.values();
} // }
//
public static void addWebSocketConnection(String sessionId, WebSocketConnection connection) { // public static void addWebSocketConnection(String sessionId, WebSocketConnection connection) {
sessionConnectionMap.put(sessionId, connection); // sessionConnectionMap.put(sessionId, connection);
} // }
//
/** // /**
* 获取 WebSocketConnection // * 获取 WebSocketConnection
*/ // */
public static WebSocketConnection getWebSocketConnection(String sessionId) { // public static WebSocketConnection getWebSocketConnection(String sessionId) {
return sessionConnectionMap.get(sessionId); // return sessionConnectionMap.get(sessionId);
} // }
//
/** // /**
* 移除 WebSocketConnection // * 移除 WebSocketConnection
*/ // */
public static void removeWebSocketConnection(String sessionId) { // public static void removeWebSocketConnection(String sessionId) {
sessionConnectionMap.remove(sessionId); // sessionConnectionMap.remove(sessionId);
} // }
//
/** // /**
* 检查 sessionId 是否存在 // * 检查 sessionId 是否存在
*/ // */
public static boolean containsWebSocketConnection(String sessionId) { // public static boolean containsWebSocketConnection(String sessionId) {
return sessionConnectionMap.containsKey(sessionId); // return sessionConnectionMap.containsKey(sessionId);
} // }
//
/** // /**
* 获取所有 WebSocketConnection // * 获取所有 WebSocketConnection
*/ // */
public static ConcurrentHashMap<Long, WebSocketConnection> getAllWebSocketConnections() { // public static ConcurrentHashMap<Long, WebSocketConnection> getAllWebSocketConnections() {
return webSocketSessionConnectionMap; // return webSocketSessionConnectionMap;
} // }
//
/** // /**
* 添加 WebSocketConnection // * 添加 WebSocketConnection
*/ // */
public static void addWebSocketConnectionByMachineId(Long machineId, WebSocketConnection connection) { // public static void addWebSocketConnectionByMachineId(Long machineId, WebSocketConnection connection) {
webSocketSessionConnectionMap.put(machineId, connection); // webSocketSessionConnectionMap.put(machineId, connection);
} // }
//
/** // /**
* 获取 WebSocketConnection // * 获取 WebSocketConnection
*/ // */
public static WebSocketConnection getWebSocketConnectionByMachineId(Long machineId) { // public static WebSocketConnection getWebSocketConnectionByMachineId(Long machineId) {
return webSocketSessionConnectionMap.get(machineId); // return webSocketSessionConnectionMap.get(machineId);
} // }
//
/** // /**
* 移除 WebSocketConnection // * 移除 WebSocketConnection
*/ // */
public static void removeWebSocketConnectionByMachineId(Long machineId) { // public static void removeWebSocketConnectionByMachineId(Long machineId) {
webSocketSessionConnectionMap.remove(machineId); // webSocketSessionConnectionMap.remove(machineId);
} // }
//
/** // /**
* 检查 machineId 是否存在 // * 检查 machineId 是否存在
*/ // */
public static boolean containsMachineId(Long machineId) { // public static boolean containsMachineId(Long machineId) {
return webSocketSessionConnectionMap.containsKey(machineId); // return webSocketSessionConnectionMap.containsKey(machineId);
} // }
//
} //}

View File

@ -1,40 +1,40 @@
package cd.casic.module.machine.configuration; //package cd.casic.module.machine.configuration;
//
import cd.casic.module.machine.Interceptor.WebSocketHandshakeInterceptor; //import cd.casic.module.machine.Interceptor.WebSocketHandshakeInterceptor;
import cd.casic.module.machine.handler.MachineWebSocketHandler; //import cd.casic.module.machine.handler.MachineWebSocketHandler;
import jakarta.annotation.Resource; //import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean; //import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; //import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket; //import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; //import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; //import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; //import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; //import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
//
@Configuration //@Configuration
@EnableWebSocket //@EnableWebSocket
//WebSocket端点配置 ////WebSocket端点配置
public class WebSocketConfig implements WebSocketConfigurer { //public class WebSocketConfig implements WebSocketConfigurer {
@Resource // @Resource
private MachineWebSocketHandler machineWebSocketHandler; // private MachineWebSocketHandler machineWebSocketHandler;
//
@Resource // @Resource
private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor; // private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor;
//
@Override // @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { // public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(machineWebSocketHandler, "/ssh/terminal") // registry.addHandler(machineWebSocketHandler, "/ssh/terminal")
.addInterceptors(webSocketHandshakeInterceptor) // .addInterceptors(webSocketHandshakeInterceptor)
.setAllowedOrigins("*"); // 允许跨域生产环境需限制 // .setAllowedOrigins("*"); // 允许跨域生产环境需限制
} // }
//
@Bean // @Bean
public ServletServerContainerFactoryBean createWebSocketContainer() { // public ServletServerContainerFactoryBean createWebSocketContainer() {
return new ServletServerContainerFactoryBean(); // return new ServletServerContainerFactoryBean();
} // }
//
@Bean // @Bean
public ServerEndpointExporter serverEndpointExporter() { // public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter(); // return new ServerEndpointExporter();
} // }
} //}

View File

@ -78,38 +78,38 @@ public class MachineInfoController {
return success(true); return success(true);
} }
@GetMapping("/test") // @GetMapping("/test")
@Operation(summary = "测试机器连接") // @Operation(summary = "测试机器连接")
public CommonResult<Boolean> testConnection(@RequestParam("id") Long id) { // public CommonResult<Boolean> testConnection(@RequestParam("id") Long id) {
return success(machineInfoService.testConnection(id)); // return success(machineInfoService.testConnection(id));
} // }
//
// @GetMapping("/status")
// @Operation(summary = "获取机器连接状态")
// public CommonResult<ConnectionStatus> getConnectionStatus(@RequestParam Long id) {
// return success(machineInfoService.getConnectionStatus(id));
// }
//
// @GetMapping("/status/all")
// @Operation(summary = "获取所有机器连接状态")
// public CommonResult<Map<Long, ConnectionStatus>> getAllConnectionStatus() {
// return success(machineInfoService.getAllConnectionStatus());
// }
//
// @GetMapping("/connect")
// @Operation(summary = "建立连接")
// public CommonResult<Map<String, Object>> connect(@RequestParam Long id) {
// return success(machineInfoService.connect(id));
// }
@GetMapping("/status") // @GetMapping("/fileTreeNode")
@Operation(summary = "获取机器连接状态") // @Operation(summary = "获得文件树")
public CommonResult<ConnectionStatus> getConnectionStatus(@RequestParam Long id) { // public CommonResult<Map<String, Object>> fileTreeNode(
return success(machineInfoService.getConnectionStatus(id)); // @RequestParam Long machineId,
} // @RequestParam(required = false, defaultValue = "/") String path
// ) {
@GetMapping("/status/all") // return CommonResult.success(machineInfoService.fileTreeNode(machineId, path));
@Operation(summary = "获取所有机器连接状态") // }
public CommonResult<Map<Long, ConnectionStatus>> getAllConnectionStatus() {
return success(machineInfoService.getAllConnectionStatus());
}
@GetMapping("/connect")
@Operation(summary = "建立连接")
public CommonResult<Map<String, Object>> connect(@RequestParam Long id) {
return success(machineInfoService.connect(id));
}
@GetMapping("/fileTreeNode")
@Operation(summary = "获得文件树")
public CommonResult<Map<String, Object>> fileTreeNode(
@RequestParam Long machineId,
@RequestParam(required = false, defaultValue = "/") String path
) {
return CommonResult.success(machineInfoService.fileTreeNode(machineId, path));
}
// @GetMapping("/upload") // @GetMapping("/upload")
// @Operation(summary = "上传文件到远程机器") // @Operation(summary = "上传文件到远程机器")
// public CommonResult<Boolean> uploadFile( // public CommonResult<Boolean> uploadFile(

View File

@ -39,9 +39,11 @@ public class MachineInfoDO extends BaseDO {
@TableField(value = "description") @TableField(value = "description")
private String description; private String description;
//1Linux 2Windows
@TableField(value = "machine_info_type") @TableField(value = "machine_info_type")
private Integer machineInfoType; private Integer machineInfoType;
// 1启用 0停用
@TableField(value = "status") @TableField(value = "status")
private Integer status; private Integer status;
@ -62,6 +64,7 @@ public class MachineInfoDO extends BaseDO {
@TableField(value = "machine_proxy_id") @TableField(value = "machine_proxy_id")
private Long machineProxyId; private Long machineProxyId;
//1密码认证 2密钥认证
@TableField(value = "authentication_type") @TableField(value = "authentication_type")
private Integer authenticationType; private Integer authenticationType;

View File

@ -34,14 +34,12 @@ public class MachineProxyDO extends BaseDO {
@TableField(value = "ssh_port") @TableField(value = "ssh_port")
private String sshPort; private String sshPort;
//todo 字典
@TableField(value = "proxy_type") @TableField(value = "proxy_type")
private int proxyType; private int proxyType;
@TableField(value = "version") @TableField(value = "version")
private String version; private String version;
//todo 字典
@TableField(value = "status") @TableField(value = "status")
private int status; private int status;

View File

@ -1,67 +1,67 @@
package cd.casic.module.machine.handler; //package cd.casic.module.machine.handler;
//
import cd.casic.module.machine.component.WebSocketConnection; ////import cd.casic.module.machine.component.WebSocketConnection;
import cd.casic.module.machine.component.WebSocketSessionManager; ////import cd.casic.module.machine.component.WebSocketSessionManager;
import cd.casic.module.machine.enums.ConnectionStatus; //import cd.casic.module.machine.enums.ConnectionStatus;
import org.jetbrains.annotations.NotNull; //import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus; //import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; //import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; //import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler; //import org.springframework.web.socket.handler.TextWebSocketHandler;
//
import java.io.IOException; //import java.io.IOException;
//
import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; //import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; //import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
//
//WebSocket处理器 ////WebSocket处理器
@Component("machineWebSocketHandler") //@Component("machineWebSocketHandler")
public class MachineWebSocketHandler extends TextWebSocketHandler { //public class MachineWebSocketHandler extends TextWebSocketHandler {
//
@Override // @Override
public void afterConnectionEstablished(@NotNull WebSocketSession webSocketSession) { // public void afterConnectionEstablished(@NotNull WebSocketSession webSocketSession) {
Long machineId = (Long) webSocketSession.getAttributes().get("machineId"); // Long machineId = (Long) webSocketSession.getAttributes().get("machineId");
//保存webSocketSession信息 // //保存webSocketSession信息
WebSocketSessionManager.addWebSocketSession(webSocketSession.getId(), webSocketSession); // WebSocketSessionManager.addWebSocketSession(webSocketSession.getId(), webSocketSession);
WebSocketSessionManager.addWebSocketConnection(webSocketSession.getId(), WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId)); // WebSocketSessionManager.addWebSocketConnection(webSocketSession.getId(), WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId));
try { // try {
webSocketSession.sendMessage(new TextMessage("欢迎连接到 WebSocket 服务器!")); // webSocketSession.sendMessage(new TextMessage("欢迎连接到 WebSocket 服务器!"));
} catch (IOException e) { // } catch (IOException e) {
throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); // throw exception(WEBSOCKET_SEND_MESSAGE_ERROR);
} // }
} // }
//
// 处理文本消息 // // 处理文本消息
@Override // @Override
protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) { // protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) {
String payload = message.getPayload(); // String payload = message.getPayload();
String sessionId = webSocketSession.getId(); // String sessionId = webSocketSession.getId();
// 从管理器获取连接 // // 从管理器获取连接
WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); // WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId);
//
if (webSocketConnection != null && ConnectionStatus.CONNECTING.equals(webSocketConnection.getConnectionStatus())) { // if (webSocketConnection != null && ConnectionStatus.CONNECTING.equals(webSocketConnection.getConnectionStatus())) {
// 转发消息到远程机器 // // 转发消息到远程机器
webSocketConnection.executeCommand(webSocketSession, payload); // webSocketConnection.executeCommand(webSocketSession, payload);
} else if (webSocketConnection != null) { // } else if (webSocketConnection != null) {
webSocketConnection.sendErrorMessage(webSocketSession, "连接已断开,无法发送消息"); // webSocketConnection.sendErrorMessage(webSocketSession, "连接已断开,无法发送消息");
} else { // } else {
throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); // throw exception(WEBSOCKET_SEND_MESSAGE_ERROR);
} // }
} // }
//
@Override // @Override
public void afterConnectionClosed(WebSocketSession webSocketSession, @NotNull CloseStatus status) { // public void afterConnectionClosed(WebSocketSession webSocketSession, @NotNull CloseStatus status) {
String sessionId = webSocketSession.getId(); // String sessionId = webSocketSession.getId();
// 获取并关闭相关的 WebSocketConnection // // 获取并关闭相关的 WebSocketConnection
WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); // WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId);
if (webSocketConnection != null) { // if (webSocketConnection != null) {
webSocketConnection.disconnect(); // webSocketConnection.disconnect();
} // }
// 从管理器中移除会话和连接 // // 从管理器中移除会话和连接
WebSocketSessionManager.removeWebSocketSession(sessionId); // WebSocketSessionManager.removeWebSocketSession(sessionId);
WebSocketSessionManager.removeWebSocketConnection(sessionId); // WebSocketSessionManager.removeWebSocketConnection(sessionId);
Long machineInfoId = (Long) webSocketSession.getAttributes().get("machineId"); // Long machineInfoId = (Long) webSocketSession.getAttributes().get("machineId");
WebSocketSessionManager.removeWebSocketConnectionByMachineId(machineInfoId); // WebSocketSessionManager.removeWebSocketConnectionByMachineId(machineInfoId);
} // }
} //}

View File

@ -40,35 +40,35 @@ public interface MachineInfoService {
List<MachineInfoDO>selectBindMachineBySecretKey(Long secretKeyId); List<MachineInfoDO>selectBindMachineBySecretKey(Long secretKeyId);
/** // /**
* 测试机器连接 // * 测试机器连接
* // *
* @param id 机器id // * @param id 机器id
* @return 连接是否成功 // * @return 连接是否成功
*/ // */
boolean testConnection(Long id); // boolean testConnection(Long id);
//
/** // /**
* 连接远程机器 // * 连接远程机器
* // *
* @param id 机器id // * @param id 机器id
* @return 连接后端文件树 // * @return 连接后端文件树
*/ // */
Map<String, Object> connect(Long id); // Map<String, Object> connect(Long id);
//
/** // /**
* 获取机器连接状态 // * 获取机器连接状态
* // *
* @return 连接状态 // * @return 连接状态
*/ // */
ConnectionStatus getConnectionStatus(Long id); // ConnectionStatus getConnectionStatus(Long id);
//
/** // /**
* 获取所有连接状态 // * 获取所有连接状态
* // *
* @return 机器名称到连接状态的映射 // * @return 机器名称到连接状态的映射
*/ // */
Map<Long, ConnectionStatus> getAllConnectionStatus(); // Map<Long, ConnectionStatus> getAllConnectionStatus();
// /** // /**
// * 上传文件到远程机器 // * 上传文件到远程机器
@ -97,12 +97,12 @@ public interface MachineInfoService {
*/ */
MachineInfoDO validateMachineInfoExists(Long id); MachineInfoDO validateMachineInfoExists(Long id);
/** // /**
* 根据路径获得远程文件树 // * 根据路径获得远程文件树
* // *
* @param machineId 机器id // * @param machineId 机器id
* @param path 文件夹路径 // * @param path 文件夹路径
* @return 远程文件树 // * @return 远程文件树
*/ // */
Map<String, Object> fileTreeNode(Long machineId, String path); // Map<String, Object> fileTreeNode(Long machineId, String path);
} }

View File

@ -2,7 +2,7 @@ package cd.casic.module.machine.service.impl;
import cd.casic.framework.commons.pojo.PageResult; import cd.casic.framework.commons.pojo.PageResult;
import cd.casic.module.machine.component.FileTreeComponent; import cd.casic.module.machine.component.FileTreeComponent;
import cd.casic.module.machine.component.WebSocketSessionManager; //import cd.casic.module.machine.component.WebSocketSessionManager;
import cd.casic.module.machine.controller.vo.SecretKeyVO; import cd.casic.module.machine.controller.vo.SecretKeyVO;
import cd.casic.module.machine.enums.AuthenticationType; import cd.casic.module.machine.enums.AuthenticationType;
import cd.casic.module.machine.enums.MachineInfoType; import cd.casic.module.machine.enums.MachineInfoType;
@ -11,7 +11,7 @@ import cd.casic.module.machine.controller.vo.MachineInfoVO;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO; import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.enums.ConnectionStatus; import cd.casic.module.machine.enums.ConnectionStatus;
import cd.casic.module.machine.enums.MachineInfoStatus; import cd.casic.module.machine.enums.MachineInfoStatus;
import cd.casic.module.machine.component.WebSocketConnection; //import cd.casic.module.machine.component.WebSocketConnection;
import cd.casic.module.machine.service.MachineInfoService; import cd.casic.module.machine.service.MachineInfoService;
import cd.casic.module.machine.service.SecretKeyService; import cd.casic.module.machine.service.SecretKeyService;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -113,43 +113,43 @@ public class MachineInfoServiceImpl implements MachineInfoService {
} }
@Override // @Override
public boolean testConnection(Long id) { // public boolean testConnection(Long id) {
//先查询机器是否存在在判断机器可用性 // //先查询机器是否存在在判断机器可用性
MachineInfoDO machineInfoDO = validateMachineInfoExists(id); // MachineInfoDO machineInfoDO = validateMachineInfoExists(id);
validateMachineUnEnable(machineInfoDO); // validateMachineUnEnable(machineInfoDO);
log.info("测试机器连接: {}", machineInfoDO.getHostIp()); // log.info("测试机器连接: {}", machineInfoDO.getHostIp());
WebSocketConnection webSocketConnection = createWebSocketConnection(machineInfoDO); // WebSocketConnection webSocketConnection = createWebSocketConnection(machineInfoDO);
webSocketConnection.initConnection(machineInfoDO); // webSocketConnection.initConnection(machineInfoDO);
return true; // return true;
} // }
//
@Override // @Override
public Map<String, Object> connect(Long id) { // public Map<String, Object> connect(Long id) {
//todo使用代理机器的情况还未完成 // //todo使用代理机器的情况还未完成
WebSocketConnection webSocketConnection = new WebSocketConnection(this.secretKeyService); // WebSocketConnection webSocketConnection = new WebSocketConnection(this.secretKeyService);
MachineInfoDO machineInfoDO = validateMachineInfoExists(id); // MachineInfoDO machineInfoDO = validateMachineInfoExists(id);
//初始化连接 // //初始化连接
webSocketConnection.initConnection(machineInfoDO); // webSocketConnection.initConnection(machineInfoDO);
WebSocketSessionManager.addWebSocketConnectionByMachineId(id, webSocketConnection); // WebSocketSessionManager.addWebSocketConnectionByMachineId(id, webSocketConnection);
return fileTreeComponent.getRemoteFileTree(webSocketConnection.getSshSession(), "/"); // return fileTreeComponent.getRemoteFileTree(webSocketConnection.getSshSession(), "/");
} // }
//
@Override // @Override
public ConnectionStatus getConnectionStatus(Long id) { // public ConnectionStatus getConnectionStatus(Long id) {
validateMachineInfoExists(id); // validateMachineInfoExists(id);
WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnectionByMachineId(id); // WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnectionByMachineId(id);
return webSocketConnection == null ? ConnectionStatus.DISCONNECTED : webSocketConnection.getConnectionStatus(); // return webSocketConnection == null ? ConnectionStatus.DISCONNECTED : webSocketConnection.getConnectionStatus();
} // }
//
@Override // @Override
public Map<Long, ConnectionStatus> getAllConnectionStatus() { // public Map<Long, ConnectionStatus> getAllConnectionStatus() {
return WebSocketSessionManager.getAllWebSocketConnections().entrySet().stream() // return WebSocketSessionManager.getAllWebSocketConnections().entrySet().stream()
.collect(Collectors.toMap( // .collect(Collectors.toMap(
Map.Entry::getKey, // Map.Entry::getKey,
entry -> entry.getValue().getConnectionStatus() // entry -> entry.getValue().getConnectionStatus()
)); // ));
} // }
// @Override // @Override
// public boolean uploadFile(String sessionId, String localFilePath, String remoteFilePath) { // public boolean uploadFile(String sessionId, String localFilePath, String remoteFilePath) {
@ -246,12 +246,12 @@ public class MachineInfoServiceImpl implements MachineInfoService {
return machineInfoDO; return machineInfoDO;
} }
@Override // @Override
public Map<String, Object> fileTreeNode(Long machineId, String path) { // public Map<String, Object> fileTreeNode(Long machineId, String path) {
validateMachineInfoExists(machineId); // validateMachineInfoExists(machineId);
Session sshSession = WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId).getSshSession(); // Session sshSession = WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId).getSshSession();
return fileTreeComponent.getRemoteFileTree(sshSession, path); // return fileTreeComponent.getRemoteFileTree(sshSession, path);
} // }
@VisibleForTesting @VisibleForTesting
void validateMachineEnable(MachineInfoDO machineInfoDO) { void validateMachineEnable(MachineInfoDO machineInfoDO) {
@ -268,12 +268,12 @@ public class MachineInfoServiceImpl implements MachineInfoService {
} }
} }
@VisibleForTesting // @VisibleForTesting
WebSocketConnection createWebSocketConnection(MachineInfoDO machineInfoDO) { // WebSocketConnection createWebSocketConnection(MachineInfoDO machineInfoDO) {
if (WebSocketSessionManager.containsMachineId(machineInfoDO.getId())) { // if (WebSocketSessionManager.containsMachineId(machineInfoDO.getId())) {
return WebSocketSessionManager.getWebSocketConnectionByMachineId((machineInfoDO.getId())); // return WebSocketSessionManager.getWebSocketConnectionByMachineId((machineInfoDO.getId()));
} else { // } else {
return new WebSocketConnection(this.secretKeyService); // return new WebSocketConnection(this.secretKeyService);
} // }
} // }
} }