feat: 主机终端访问.

This commit is contained in:
lijiahang
2023-12-28 19:18:46 +08:00
parent 638fbb9613
commit a1e372148a
22 changed files with 254 additions and 308 deletions

View File

@@ -1,15 +1,17 @@
package com.orion.ops.framework.biz.operator.log.core.constant; package com.orion.ops.framework.common.constant;
import com.orion.ops.framework.common.constant.FieldConst;
/** /**
* 操作日志常量 * 额外字段常量
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2023/10/10 19:00 * @since 2023/12/28 18:34
*/ */
public interface OperatorLogKeys extends FieldConst { public interface ExtraFieldConst extends FieldConst {
String USER_ID = "userId";
String TRACE_ID = "traceId";
String GROUP_NAME = "groupName"; String GROUP_NAME = "groupName";

View File

@@ -3,7 +3,7 @@ package com.orion.ops.framework.common.entity;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 请求身份 * 请求留痕
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0

View File

@@ -20,7 +20,7 @@ public class Requests {
} }
/** /**
* 填充请求身份信息 * 填充请求留痕信息
* *
* @param identity identity * @param identity identity
*/ */

View File

@@ -242,7 +242,7 @@ public class OperatorLogAspect {
} }
/** /**
* 填充请求信息 * 填充请求留痕信息
* *
* @param model model * @param model model
*/ */

View File

@@ -2,7 +2,7 @@ package com.orion.ops.framework.biz.operator.log.core.uitls;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeFilter; import com.alibaba.fastjson.serializer.SerializeFilter;
import com.orion.ops.framework.biz.operator.log.core.constant.OperatorLogKeys; import com.orion.ops.framework.common.constant.ExtraFieldConst;
import com.orion.ops.framework.common.security.LoginUser; import com.orion.ops.framework.common.security.LoginUser;
import java.util.HashMap; import java.util.HashMap;
@@ -15,7 +15,7 @@ import java.util.Map;
* @version 1.0.0 * @version 1.0.0
* @since 2023/10/10 11:32 * @since 2023/10/10 11:32
*/ */
public class OperatorLogs implements OperatorLogKeys { public class OperatorLogs implements ExtraFieldConst {
private static final String UN_SAVE_FLAG = "__un__save__"; private static final String UN_SAVE_FLAG = "__un__save__";

View File

@@ -1,13 +1,11 @@
package com.orion.ops.framework.websocket.config; package com.orion.ops.framework.websocket.config;
import com.orion.ops.framework.common.constant.AutoConfigureOrderConst; import com.orion.ops.framework.common.constant.AutoConfigureOrderConst;
import com.orion.ops.framework.websocket.core.interceptor.UserHandshakeInterceptor;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
/** /**
@@ -35,12 +33,4 @@ public class OrionWebSocketAutoConfiguration {
return factory; return factory;
} }
/**
* @return 用户认证拦截器 按需注入
*/
@Bean
public HandshakeInterceptor userHandshakeInterceptor() {
return new UserHandshakeInterceptor();
}
} }

View File

@@ -1,22 +0,0 @@
package com.orion.ops.framework.websocket.core.constant;
/**
* websocket 属性
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/6/25 20:25
*/
public interface WsAttr {
String USER = "user";
String UID = "uid";
String TOKEN = "token";
String READONLY = "readonly";
String CONNECTED = "connected";
}

View File

@@ -1,79 +0,0 @@
package com.orion.ops.framework.websocket.core.constant;
import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.Valid;
import lombok.AllArgsConstructor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* ws服务端响应常量
*
* @author Jiahang Li
* @version 1.0.0
* @since 2021/4/16 21:48
*/
@AllArgsConstructor
public enum WsProtocol {
/**
* 正常返回
*/
OK("0"),
/**
* 连接成功
*/
CONNECTED("1"),
/**
* ping
*/
PING("2"),
/**
* pong
*/
PONG("3"),
/**
* 未知操作
*/
ERROR("4"),
;
private final String code;
/**
* 分隔符
*/
public static final String SYMBOL = "|";
public byte[] get() {
return Strings.bytes(code);
}
public byte[] msg(String body) {
Valid.notNull(body);
return this.msg(Strings.bytes(body));
}
public byte[] msg(byte[] body) {
return this.msg(body, 0, body.length);
}
public byte[] msg(byte[] body, int offset, int len) {
Valid.notNull(body);
try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
o.write(Strings.bytes(code + SYMBOL));
o.write(body, offset, len);
return o.toByteArray();
} catch (IOException e) {
throw Exceptions.ioRuntime(e);
}
}
}

View File

@@ -1,41 +0,0 @@
package com.orion.ops.framework.websocket.core.interceptor;
import com.orion.ops.framework.common.security.SecurityHolder;
import com.orion.ops.framework.websocket.core.constant.WsAttr;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import javax.annotation.Resource;
import java.util.Map;
/**
* 用户拦截器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/6/25 20:16
*/
public class UserHandshakeInterceptor implements HandshakeInterceptor {
@Resource
private SecurityHolder securityHolder;
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
// TODO TEST
attributes.put(WsAttr.USER, securityHolder.getLoginUserId());
// if (user == null){
// return false;
// response.setStatusCode(HttpStatus.MULTI_STATUS);
// }
// HttpSessionHandshakeInterceptor
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}

View File

@@ -0,0 +1,39 @@
package com.orion.ops.module.asset.config;
import com.orion.ops.module.asset.handler.host.terminal.TerminalDispatchHandler;
import com.orion.ops.module.asset.interceptor.TerminalInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import javax.annotation.Resource;
/**
* 资产模块 websocket 配置
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/12/28 11:39
*/
@Configuration
public class AssetWebSocketConfiguration implements WebSocketConfigurer {
@Value("${orion.websocket.prefix}")
private String prefix;
@Resource
private TerminalInterceptor terminalInterceptor;
@Resource
private TerminalDispatchHandler terminalDispatchHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 终端
registry.addHandler(terminalDispatchHandler, prefix + "/host/terminal/{token}")
.addInterceptors(terminalInterceptor)
.setAllowedOrigins("*");
}
}

View File

@@ -1,11 +1,6 @@
### 获取主机终端连接 token ### 获取主机终端连接 token
POST {{baseUrl}}/asset/host-terminal/access GET {{baseUrl}}/asset/host-terminal/access
Content-Type: application/json
Authorization: {{token}} Authorization: {{token}}
{
"hostId": 1
}
### ###

View File

@@ -1,18 +1,14 @@
package com.orion.ops.module.asset.controller; package com.orion.ops.module.asset.controller;
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.ops.framework.security.core.utils.SecurityUtils; import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.framework.web.core.annotation.RestWrapper; import com.orion.ops.framework.web.core.annotation.RestWrapper;
import com.orion.ops.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.ops.module.asset.entity.request.host.HostTerminalConnectRequest;
import com.orion.ops.module.asset.service.HostTerminalService; import com.orion.ops.module.asset.service.HostTerminalService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -37,12 +33,11 @@ public class HostTerminalController {
@Resource @Resource
private HostTerminalService hostTerminalService; private HostTerminalService hostTerminalService;
@OperatorLog(HostTerminalOperatorType.ACCESS) @GetMapping("/access")
@PostMapping("/access") @Operation(summary = "获取主机终端 accessToken")
@Operation(summary = "获取主机终端连接 token")
@PreAuthorize("@ss.hasPermission('asset:host-terminal:access')") @PreAuthorize("@ss.hasPermission('asset:host-terminal:access')")
public String getHostAccessToken(@Validated @RequestBody HostTerminalConnectRequest request) { public String getHostTerminalAccessToken() {
return hostTerminalService.getHostAccessToken(request.getHostId(), SecurityUtils.getLoginUserId()); return hostTerminalService.getHostTerminalAccessToken(SecurityUtils.getLoginUserId());
} }
} }

View File

@@ -1,7 +1,7 @@
package com.orion.ops.module.asset.convert; package com.orion.ops.module.asset.convert;
import com.orion.ops.module.asset.entity.domain.HostConnectLogDO; import com.orion.ops.module.asset.entity.domain.HostConnectLogDO;
import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO; 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.entity.request.host.HostConnectLogCreateRequest;
import com.orion.ops.module.asset.entity.request.host.HostConnectLogQueryRequest; import com.orion.ops.module.asset.entity.request.host.HostConnectLogQueryRequest;
import com.orion.ops.module.asset.entity.vo.HostConnectLogVO; import com.orion.ops.module.asset.entity.vo.HostConnectLogVO;
@@ -28,7 +28,7 @@ public interface HostConnectLogConvert {
HostConnectLogVO to(HostConnectLogDO domain); HostConnectLogVO to(HostConnectLogDO domain);
HostConnectLogCreateRequest to(HostSshConnectDTO dto); HostConnectLogCreateRequest to(HostTerminalConnectDTO dto);
List<HostConnectLogVO> to(List<HostConnectLogDO> list); List<HostConnectLogVO> to(List<HostConnectLogDO> list);

View File

@@ -3,7 +3,7 @@ package com.orion.ops.module.asset.define.cache;
import com.orion.lang.define.cache.key.CacheKeyBuilder; import com.orion.lang.define.cache.key.CacheKeyBuilder;
import com.orion.lang.define.cache.key.CacheKeyDefine; import com.orion.lang.define.cache.key.CacheKeyDefine;
import com.orion.lang.define.cache.key.struct.RedisCacheStruct; import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -16,10 +16,10 @@ import java.util.concurrent.TimeUnit;
*/ */
public interface HostTerminalCacheKeyDefine { public interface HostTerminalCacheKeyDefine {
CacheKeyDefine HOST_TERMINAL_CONNECT = new CacheKeyBuilder() CacheKeyDefine HOST_TERMINAL_ACCESS = new CacheKeyBuilder()
.key("host:terminal:connect:{}") .key("host:terminal:access:{}")
.desc("主机终端连接信息 ${token}") .desc("主机终端访问token ${token}")
.type(HostSshConnectDTO.class) .type(HostTerminalAccessDTO.class)
.struct(RedisCacheStruct.STRING) .struct(RedisCacheStruct.STRING)
.timeout(3, TimeUnit.MINUTES) .timeout(3, TimeUnit.MINUTES)
.build(); .build();

View File

@@ -16,12 +16,12 @@ import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLe
@Module("asset:host-terminal") @Module("asset:host-terminal")
public class HostTerminalOperatorType extends InitializingOperatorTypes { public class HostTerminalOperatorType extends InitializingOperatorTypes {
public static final String ACCESS = "host-terminal:access"; public static final String CONNECT = "host-terminal:connect";
@Override @Override
public OperatorType[] types() { public OperatorType[] types() {
return new OperatorType[]{ return new OperatorType[]{
new OperatorType(L, ACCESS, "连接主机终端 <sb>${hostName}</sb>"), new OperatorType(L, CONNECT, "连接主机终端 <sb>${hostName}</sb>"),
}; };
} }

View File

@@ -0,0 +1,31 @@
package com.orion.ops.module.asset.entity.dto;
import com.orion.ops.framework.desensitize.core.annotation.DesensitizeObject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 主机终端访问参数
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/12/26 15:47
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DesensitizeObject
@Schema(name = "HostTerminalAccessDTO", description = "主机终端访问参数")
public class HostTerminalAccessDTO {
@Schema(description = "userId")
private Long userId;
@Schema(description = "token")
private String token;
}

View File

@@ -9,7 +9,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/** /**
* 主机连接参数 * 主机终端连接参数
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -20,8 +20,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@DesensitizeObject @DesensitizeObject
@Schema(name = "HostSshConnectDTO", description = "主机连接参数") @Schema(name = "HostTerminalConnectDTO", description = "主机终端连接参数")
public class HostSshConnectDTO { public class HostTerminalConnectDTO {
@Schema(description = "token") @Schema(description = "token")
private String token; private String token;

View File

@@ -1,30 +0,0 @@
package com.orion.ops.module.asset.entity.request.host;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 主机终端连接 请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-20 11:55
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "HostTerminalConnectRequest", description = "主机终端连接 请求对象")
public class HostTerminalConnectRequest implements Serializable {
@NotNull
@Schema(description = "hostId")
private Long hostId;
}

View File

@@ -0,0 +1,52 @@
package com.orion.ops.module.asset.handler.host.terminal;
import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFrameworkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/**
* 终端处理器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/12/28 14:33
*/
@Slf4j
@Component
public class TerminalDispatchHandler implements WebSocketHandler {
@Resource
private OperatorLogFrameworkService operatorLogFrameworkService;
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
log.info("afterConnectionEstablished");
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
log.info("handleMessage");
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
log.info("handleTransportError");
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
log.info("afterConnectionClosed");
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}

View File

@@ -1,63 +1,57 @@
package com.orion.ops.module.asset.interceptor; package com.orion.ops.module.asset.interceptor;
import com.orion.ops.framework.websocket.core.interceptor.UserHandshakeInterceptor; import com.orion.lang.utils.Urls;
import org.springframework.context.annotation.Configuration; import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
import com.orion.ops.framework.common.constant.ExtraFieldConst;
import com.orion.ops.framework.common.entity.RequestIdentity;
import com.orion.ops.framework.common.utils.Requests;
import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.ops.module.asset.service.HostTerminalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.*; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Map;
/** /**
* 终端拦截器
*
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2023/12/27 23:53 * @since 2023/12/27 23:53
*/ */
@Configuration @Slf4j
public class TerminalInterceptor implements WebSocketConfigurer { @Component
public class TerminalInterceptor implements HandshakeInterceptor {
// https://blog.csdn.net/oNew_Lifeo/article/details/130003676
// https://wstool.js.org/
@Resource @Resource
private UserHandshakeInterceptor userHandshakeInterceptor; private HostTerminalService hostTerminalService;
@Override @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
registry.addHandler(new WebSocketHandler1(), "/orion/keep-alive/host/terminal") // 获取 token
.addInterceptors(userHandshakeInterceptor) String token = Urls.getUrlSource(request.getURI().getPath());
.setAllowedOrigins("*"); log.info("TerminalInterceptor-beforeHandshake start token: {}", token);
System.out.println("123"); // 获取连接数据
} HostTerminalAccessDTO access = hostTerminalService.getAccessInfoByToken(token);
if (access == null) {
static class WebSocketHandler1 implements WebSocketHandler { log.error("TerminalInterceptor-beforeHandshake absent token: {}", token);
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println(1);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
System.out.println(message);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println(1);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
System.out.println(1);
}
@Override
public boolean supportsPartialMessages() {
return false; return false;
} }
// 设置参数
attributes.put(ExtraFieldConst.USER_ID, access.getUserId());
OperatorLogModel identity = new OperatorLogModel();
Requests.fillIdentity(identity);
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
log.info("afterHandshake");
} }
} }

View File

@@ -1,7 +1,8 @@
package com.orion.ops.module.asset.service; package com.orion.ops.module.asset.service;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
/** /**
* 主机终端服务 * 主机终端服务
@@ -13,21 +14,29 @@ import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO;
public interface HostTerminalService { public interface HostTerminalService {
/** /**
* 获取主机终端连接 token * 获取主机终端访问 accessToken
*
* @param userId userId
* @return session
*/
String getHostTerminalAccessToken(Long userId);
/**
* 通过 accessToken 获取主机终端访问信息
*
* @param token token
* @return config
*/
HostTerminalAccessDTO getAccessInfoByToken(String token);
/**
* 使用用户配置打开获取连接信息
* *
* @param hostId hostId * @param hostId hostId
* @param userId userId * @param userId userId
* @return session * @return session
*/ */
String getHostAccessToken(Long hostId, Long userId); HostTerminalConnectDTO getTerminalConnectInfo(Long userId, Long hostId);
/**
* 通过 token 获取主机终端连接信息
*
* @param token token
* @return config
*/
HostSshConnectDTO getConnectInfoByToken(String token);
/** /**
* 使用默认配置打开主机会话 * 使用默认配置打开主机会话
@@ -43,6 +52,6 @@ public interface HostTerminalService {
* @param conn conn * @param conn conn
* @return session * @return session
*/ */
SessionStore openSessionStore(HostSshConnectDTO conn); SessionStore openSessionStore(HostTerminalConnectDTO conn);
} }

View File

@@ -6,13 +6,11 @@ import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.Strings; import com.orion.lang.utils.Strings;
import com.orion.net.host.SessionHolder; import com.orion.net.host.SessionHolder;
import com.orion.net.host.SessionStore; import com.orion.net.host.SessionStore;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.CryptoUtils; import com.orion.ops.framework.common.utils.CryptoUtils;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings; import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.module.asset.convert.HostConnectLogConvert;
import com.orion.ops.module.asset.dao.HostDAO; import com.orion.ops.module.asset.dao.HostDAO;
import com.orion.ops.module.asset.dao.HostIdentityDAO; import com.orion.ops.module.asset.dao.HostIdentityDAO;
import com.orion.ops.module.asset.dao.HostKeyDAO; import com.orion.ops.module.asset.dao.HostKeyDAO;
@@ -20,9 +18,12 @@ import com.orion.ops.module.asset.define.cache.HostTerminalCacheKeyDefine;
import com.orion.ops.module.asset.entity.domain.HostDO; import com.orion.ops.module.asset.entity.domain.HostDO;
import com.orion.ops.module.asset.entity.domain.HostIdentityDO; import com.orion.ops.module.asset.entity.domain.HostIdentityDO;
import com.orion.ops.module.asset.entity.domain.HostKeyDO; import com.orion.ops.module.asset.entity.domain.HostKeyDO;
import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO; import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO;
import com.orion.ops.module.asset.entity.request.host.HostConnectLogCreateRequest; import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
import com.orion.ops.module.asset.enums.*; import com.orion.ops.module.asset.enums.HostConfigTypeEnum;
import com.orion.ops.module.asset.enums.HostExtraItemEnum;
import com.orion.ops.module.asset.enums.HostExtraSshAuthTypeEnum;
import com.orion.ops.module.asset.enums.HostSshAuthTypeEnum;
import com.orion.ops.module.asset.handler.host.config.model.HostSshConfigModel; import com.orion.ops.module.asset.handler.host.config.model.HostSshConfigModel;
import com.orion.ops.module.asset.handler.host.extra.model.HostSshExtraModel; import com.orion.ops.module.asset.handler.host.extra.model.HostSshExtraModel;
import com.orion.ops.module.asset.service.HostConfigService; import com.orion.ops.module.asset.service.HostConfigService;
@@ -79,8 +80,34 @@ public class HostTerminalServiceImpl implements HostTerminalService {
private SystemUserApi systemUserApi; private SystemUserApi systemUserApi;
@Override @Override
public String getHostAccessToken(Long hostId, Long userId) { public String getHostTerminalAccessToken(Long userId) {
log.info("HostConnectService.getHostAccessToken hostId: {}, userId: {}", hostId, userId); log.info("HostConnectService.getHostAccessToken userId: {}", userId);
String token = UUIds.random19();
HostTerminalAccessDTO access = HostTerminalAccessDTO.builder()
.token(token)
.userId(userId)
.build();
// 设置缓存
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_ACCESS.format(token);
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_ACCESS, access);
return token;
}
@Override
public HostTerminalAccessDTO getAccessInfoByToken(String token) {
// 获取缓存
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_ACCESS.format(token);
HostTerminalAccessDTO access = RedisStrings.getJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_ACCESS);
// 删除缓存
if (access != null) {
RedisStrings.delete(key);
}
return access;
}
@Override
public HostTerminalConnectDTO getTerminalConnectInfo(Long userId, Long hostId) {
log.info("HostConnectService.getTerminalConnectInfo hostId: {}, userId: {}", hostId, userId);
// 查询主机 // 查询主机
HostDO host = hostDAO.selectById(hostId); HostDO host = hostDAO.selectById(hostId);
Valid.notNull(host, ErrorMessage.HOST_ABSENT); Valid.notNull(host, ErrorMessage.HOST_ABSENT);
@@ -115,27 +142,11 @@ public class HostTerminalServiceImpl implements HostTerminalService {
} }
} }
} }
String token = UUIds.random32();
// 获取连接配置 // 获取连接配置
HostSshConnectDTO connect = this.getHostConnectInfo(host, config, extra); HostTerminalConnectDTO connect = this.getHostConnectInfo(host, config, extra);
connect.setUserId(userId); connect.setUserId(userId);
connect.setToken(token); connect.setToken(UUIds.random15());
// 设置缓存 return connect;
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT.format(token);
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT, connect);
// 记录连接日志
HostConnectLogCreateRequest log = HostConnectLogConvert.MAPPER.to(connect);
log.setUsername(user.getUsername());
hostConnectLogService.create(HostConnectTypeEnum.SSH, log);
// 设置日志参数
OperatorLogs.add(connect);
return token;
}
@Override
public HostSshConnectDTO getConnectInfoByToken(String token) {
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT.format(token);
return RedisStrings.getJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT);
} }
@Override @Override
@@ -148,13 +159,13 @@ public class HostTerminalServiceImpl implements HostTerminalService {
HostSshConfigModel model = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH); HostSshConfigModel model = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
Valid.notNull(model, ErrorMessage.CONFIG_ABSENT); Valid.notNull(model, ErrorMessage.CONFIG_ABSENT);
// 获取配置 // 获取配置
HostSshConnectDTO connect = this.getHostConnectInfo(host, model, null); HostTerminalConnectDTO connect = this.getHostConnectInfo(host, model, null);
// 打开连接 // 打开连接
return this.openSessionStore(connect); return this.openSessionStore(connect);
} }
@Override @Override
public SessionStore openSessionStore(HostSshConnectDTO conn) { public SessionStore openSessionStore(HostTerminalConnectDTO conn) {
Long hostId = conn.getHostId(); Long hostId = conn.getHostId();
String address = conn.getHostAddress(); String address = conn.getHostAddress();
String username = conn.getUsername(); String username = conn.getUsername();
@@ -212,9 +223,9 @@ public class HostTerminalServiceImpl implements HostTerminalService {
* @param extra extra * @param extra extra
* @return session * @return session
*/ */
private HostSshConnectDTO getHostConnectInfo(HostDO host, private HostTerminalConnectDTO getHostConnectInfo(HostDO host,
HostSshConfigModel config, HostSshConfigModel config,
HostSshExtraModel extra) { HostSshExtraModel extra) {
// 获取认证方式 // 获取认证方式
HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType()); HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType());
HostExtraSshAuthTypeEnum extraAuthType = Optional.ofNullable(extra) HostExtraSshAuthTypeEnum extraAuthType = Optional.ofNullable(extra)
@@ -235,7 +246,7 @@ public class HostTerminalServiceImpl implements HostTerminalService {
} }
Long keyId = null; Long keyId = null;
// 填充认证信息 // 填充认证信息
HostSshConnectDTO conn = new HostSshConnectDTO(); HostTerminalConnectDTO conn = new HostTerminalConnectDTO();
conn.setHostId(host.getId()); conn.setHostId(host.getId());
conn.setHostName(host.getName()); conn.setHostName(host.getName());
conn.setHostAddress(host.getAddress()); conn.setHostAddress(host.getAddress());