diff options
| author | shizhendong <[email protected]> | 2023-02-16 17:04:10 +0800 |
|---|---|---|
| committer | shizhendong <[email protected]> | 2023-02-16 17:04:10 +0800 |
| commit | ba07487a5b205b5ee968c03c48892a8ce4420306 (patch) | |
| tree | 3ea5cf7a872f5128b9217497a5917de11ab0a882 | |
| parent | b2281166c2b12a2064c8710c42981528c625e696 (diff) | |
fix: NEZ-2541 修复 terminal 复制会话异常问题
1. 参考 XShell,修复会话改为使用账号信息重新登录方式
2. 解决关闭 websocket 时,terminal session 状态更新异常问题
3 files changed, 74 insertions, 16 deletions
diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java index 1d2af4e2..2e1c5c3f 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java @@ -296,40 +296,54 @@ public class TerminalHandler extends TextWebSocketHandler { @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { try { - log.info("Connection Closed. process terminal related information begin..."); + log.info("[afterConnectionClosed] [WebSocket connection closed] [websocket uri: {}]", session.getUri()); super.afterConnectionClosed(session, status); + + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(session); + log.info("[afterConnectionClosed] [Close terminal client connection] [clientId: {}]", ObjectUtil.isNull(terminalClient) ? null : terminalClient.getClientId()); + if (ObjectUtil.isNull(terminalClient)) { + log.warn("[afterConnectionClosed] [failed to get terminal client through websocket connection.] [websocket uri: {}]", session.getUri()); + return; + } + + // close terminal this.closeTerminal(session); + // client id + String clientId = terminalClient.getClientId(); + // client 关闭后,处理 session 和 record 信息 - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); + TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionEntity"); if (Tool.ObjectUtil.isNotNull(sessionEntity)) { + log.info("[afterConnectionClosed] [udpate session status] [session id: {}] [status: {}]", sessionEntity.getUuid(), sessionEntity.getStatus()); // 正常连接状态 关闭窗口,将状态改为 已结束,其他不做处理 if (TerminalConstant.SessionStatus.CONNECTING.getValue() == sessionEntity.getStatus()) { sessionEntity.setStatus(TerminalConstant.SessionStatus.OVER.getValue()); } sessionEntity.setEndTime(new Date()); - - log.info("Connection Closed, udpate session status is over. session id: {}, entity info: {}", uuid, JSONUtil.toJsonStr(sessionEntity)); terminalSessionService.saveOrUpdate(sessionEntity); // save Record Content After Client Closed - TerminalHandler.saveRecordContentAfterClientClosed(uuid); + TerminalHandler.saveRecordContentAfterClientClosed(clientId); + } else { + log.warn("[afterConnectionClosed] [not found TerminalSessionEntity through client id.] [clientId: {}]", clientId); } // remove Terminal Attribute Info - TerminalSession.removeTerminalAttributeInfo(uuid); + TerminalSession.removeTerminalAttributeInfo(clientId); // monitor terminal session - List<WebSocketSession> monitorWebSocketSessions = TerminalSession.TERMINAL_MONITORS_MAPPING.get(uuid); + List<WebSocketSession> monitorWebSocketSessions = TerminalSession.TERMINAL_MONITORS_MAPPING.get(clientId); if (Tool.CollUtil.isNotEmpty(monitorWebSocketSessions)) { + log.info("[afterConnectionClosed] [close monitor windows] [size: {}]", monitorWebSocketSessions.size()); for (WebSocketSession socketSession : monitorWebSocketSessions) { socketSession.sendMessage(new TextMessage("\u001B[01;31m\u001B[KConnection closed \u001B[m\u001B[K")); } - TerminalSession.TERMINAL_MONITORS_MAPPING.remove(uuid); + TerminalSession.TERMINAL_MONITORS_MAPPING.remove(clientId); } - log.info("Connection Closed finished."); + log.info("[afterConnectionClosed] [close resource finshed.] [clientId: {}]", clientId); } catch (Exception e) { - log.error(e, "Connection Closed error. session: {}, status: {}", session, status.toString()); + log.error(e, "[afterConnectionClosed] [error] [session: {}] [status: {}]", JSONUtil.toJsonStr(session), JSONUtil.toJsonStr(status)); throw e; } } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java index 98c23bfa..9b9913fc 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java @@ -657,14 +657,57 @@ public class TerminalSessionServiceImpl extends ServiceImpl<TerminalSessionDao, String duplicateSessionUUID = StrUtil.uuid(); log.info("[duplicateSession] [source session exists. duplicate session info] [source uuid: {}] [duplicate uuid: {}]", uuid, duplicateSessionUUID); - // duplicate session - TerminalSession.TERMINAL_CONNECTED_CACHE.put(duplicateSessionUUID, connObjMap); - - // connected last active time - TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(uuid, Tool.DateUtil.currentSeconds()); - // terminal Connection Info AssetAsset terminalConnInfo = (AssetAsset) connObjMap.get(TerminalSession.CONNECTION_ASSET_KEY); + log.info("[duplicateSession] [duplicate session source information] [asset: {}]", JSONUtil.toJsonStr(terminalConnInfo)); + + // SSH + if (TerminalConstant.ProtocolType.SSH.getValue().equals(terminalConnInfo.getAuthProtocol())) { + try { + log.info("[duplicateSession] [reopen SSH connection begin.] [duplicate uuid: {}]", duplicateSessionUUID); + Session session = SshUtil.getSshConnection(terminalConnInfo); + TerminalSession.TERMINAL_CONNECTED_CACHE.put(duplicateSessionUUID, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, session) + .map()); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(duplicateSessionUUID, Tool.DateUtil.currentSeconds()); + log.info("[duplicateSession] [reopen SSH connection success.] [duplicate uuid: {}]", duplicateSessionUUID); + } catch (Exception e) { + log.error(e, "[duplicateSession] [reopen SSH connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } + + // TELNET + if (TerminalConstant.ProtocolType.TELNET.getValue().equals(terminalConnInfo.getAuthProtocol())) { + try { + log.info("[duplicateSession] [reopen TELNET connection begin.] [duplicate uuid: {}]", duplicateSessionUUID); + TelnetUtil telnetUtil = new TelnetUtil(); + telnetUtil.connect(terminalConnInfo.getManageIp(), terminalConnInfo.getAuthProtocolPort()); + List<SysConfigEntity> configList = sysConfService.list(new LambdaQueryWrapper<SysConfigEntity>().in(SysConfigEntity::getParamKey, "terminal_telnet_user_tip", "terminal_telnet_pin_tip")); + Map<String, String> systemTipConfigMap = configList.stream().collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + + String authUserTip = TelnetUtil.getTelenetLoginTip(terminalConnInfo.getAuthUserTip(), systemTipConfigMap, "terminal_telnet_user_tip"); + String authPinTip = TelnetUtil.getTelenetLoginTip(terminalConnInfo.getAuthPinTip(), systemTipConfigMap, "terminal_telnet_pin_tip"); + boolean isLogin = telnetUtil.login(terminalConnInfo.getAuthUsername(), StringUtils.str(Base64.getDecoder().decode(terminalConnInfo.getAuthPin())), authUserTip, authPinTip); + if (isLogin) { + TerminalSession.TERMINAL_CONNECTED_CACHE.put(duplicateSessionUUID, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, telnetUtil.getTelnetClient()) + .map()); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(duplicateSessionUUID, Tool.DateUtil.currentSeconds()); + log.info("[duplicateSession] [reopen TELNET connection success.] [duplicate uuid: {}]", duplicateSessionUUID); + } else { + log.warn("[duplicateSession] [reopen TELNET connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } catch (Exception e) { + log.error(e, "[duplicateSession] [reopen TELNET connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } // return duplicate session map Map<Object, Object> duplicateSessionMap = Tool.MapUtil.builder() diff --git a/nz-common/src/main/java/com/nis/common/utils/RCode.java b/nz-common/src/main/java/com/nis/common/utils/RCode.java index ac69edc0..87e1c613 100644 --- a/nz-common/src/main/java/com/nis/common/utils/RCode.java +++ b/nz-common/src/main/java/com/nis/common/utils/RCode.java @@ -831,6 +831,7 @@ public enum RCode { TERMINAL_NEW_PATH_ISNULL(611021, "File new path cannot be empty"), TERMINAL_MKDIR_DIR_ALREADY_EXISTS(612022, "The specified file name already exists, please enter another name."), TERMINAL_LS_FOLDER_ERROR(616023, "Cannot display remote folder"), + TERMINAL_DUPLICATE_SESSION_FAILED(618024, "Duplicate session failed."), /** * LINK |
