feat: 主机终端访问.
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
package com.orion.ops.framework.biz.operator.log.core.constant;
|
||||
|
||||
import com.orion.ops.framework.common.constant.FieldConst;
|
||||
package com.orion.ops.framework.common.constant;
|
||||
|
||||
/**
|
||||
* 操作日志常量
|
||||
* 额外字段常量
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @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";
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.orion.ops.framework.common.entity;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 请求身份
|
||||
* 请求留痕
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
|
||||
@@ -20,7 +20,7 @@ public class Requests {
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充请求身份信息
|
||||
* 填充请求留痕信息
|
||||
*
|
||||
* @param identity identity
|
||||
*/
|
||||
|
||||
@@ -242,7 +242,7 @@ public class OperatorLogAspect {
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充请求信息
|
||||
* 填充请求留痕信息
|
||||
*
|
||||
* @param model model
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.orion.ops.framework.biz.operator.log.core.uitls;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
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 java.util.HashMap;
|
||||
@@ -15,7 +15,7 @@ import java.util.Map;
|
||||
* @version 1.0.0
|
||||
* @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__";
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.orion.ops.framework.websocket.config;
|
||||
|
||||
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.AutoConfigureOrder;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
|
||||
|
||||
/**
|
||||
@@ -35,12 +33,4 @@ public class OrionWebSocketAutoConfiguration {
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 用户认证拦截器 按需注入
|
||||
*/
|
||||
@Bean
|
||||
public HandshakeInterceptor userHandshakeInterceptor() {
|
||||
return new UserHandshakeInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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("*");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
### 获取主机终端连接 token
|
||||
POST {{baseUrl}}/asset/host-terminal/access
|
||||
Content-Type: application/json
|
||||
GET {{baseUrl}}/asset/host-terminal/access
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"hostId": 1
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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.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 io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -37,12 +33,11 @@ public class HostTerminalController {
|
||||
@Resource
|
||||
private HostTerminalService hostTerminalService;
|
||||
|
||||
@OperatorLog(HostTerminalOperatorType.ACCESS)
|
||||
@PostMapping("/access")
|
||||
@Operation(summary = "获取主机终端连接 token")
|
||||
@GetMapping("/access")
|
||||
@Operation(summary = "获取主机终端 accessToken")
|
||||
@PreAuthorize("@ss.hasPermission('asset:host-terminal:access')")
|
||||
public String getHostAccessToken(@Validated @RequestBody HostTerminalConnectRequest request) {
|
||||
return hostTerminalService.getHostAccessToken(request.getHostId(), SecurityUtils.getLoginUserId());
|
||||
public String getHostTerminalAccessToken() {
|
||||
return hostTerminalService.getHostTerminalAccessToken(SecurityUtils.getLoginUserId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orion.ops.module.asset.convert;
|
||||
|
||||
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.HostConnectLogQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.HostConnectLogVO;
|
||||
@@ -28,7 +28,7 @@ public interface HostConnectLogConvert {
|
||||
|
||||
HostConnectLogVO to(HostConnectLogDO domain);
|
||||
|
||||
HostConnectLogCreateRequest to(HostSshConnectDTO dto);
|
||||
HostConnectLogCreateRequest to(HostTerminalConnectDTO dto);
|
||||
|
||||
List<HostConnectLogVO> to(List<HostConnectLogDO> list);
|
||||
|
||||
|
||||
@@ -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.CacheKeyDefine;
|
||||
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;
|
||||
|
||||
@@ -16,10 +16,10 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public interface HostTerminalCacheKeyDefine {
|
||||
|
||||
CacheKeyDefine HOST_TERMINAL_CONNECT = new CacheKeyBuilder()
|
||||
.key("host:terminal:connect:{}")
|
||||
.desc("主机终端连接信息 ${token}")
|
||||
.type(HostSshConnectDTO.class)
|
||||
CacheKeyDefine HOST_TERMINAL_ACCESS = new CacheKeyBuilder()
|
||||
.key("host:terminal:access:{}")
|
||||
.desc("主机终端访问token ${token}")
|
||||
.type(HostTerminalAccessDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(3, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
@@ -16,12 +16,12 @@ import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLe
|
||||
@Module("asset:host-terminal")
|
||||
public class HostTerminalOperatorType extends InitializingOperatorTypes {
|
||||
|
||||
public static final String ACCESS = "host-terminal:access";
|
||||
public static final String CONNECT = "host-terminal:connect";
|
||||
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(L, ACCESS, "连接主机终端 <sb>${hostName}</sb>"),
|
||||
new OperatorType(L, CONNECT, "连接主机终端 <sb>${hostName}</sb>"),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 主机连接参数
|
||||
* 主机终端连接参数
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -20,8 +20,8 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@DesensitizeObject
|
||||
@Schema(name = "HostSshConnectDTO", description = "主机连接参数")
|
||||
public class HostSshConnectDTO {
|
||||
@Schema(name = "HostTerminalConnectDTO", description = "主机终端连接参数")
|
||||
public class HostTerminalConnectDTO {
|
||||
|
||||
@Schema(description = "token")
|
||||
private String token;
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +1,57 @@
|
||||
package com.orion.ops.module.asset.interceptor;
|
||||
|
||||
import com.orion.ops.framework.websocket.core.interceptor.UserHandshakeInterceptor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.orion.lang.utils.Urls;
|
||||
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.web.socket.*;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||
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/12/27 23:53
|
||||
*/
|
||||
@Configuration
|
||||
public class TerminalInterceptor implements WebSocketConfigurer {
|
||||
|
||||
// https://blog.csdn.net/oNew_Lifeo/article/details/130003676
|
||||
// https://wstool.js.org/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TerminalInterceptor implements HandshakeInterceptor {
|
||||
|
||||
@Resource
|
||||
private UserHandshakeInterceptor userHandshakeInterceptor;
|
||||
private HostTerminalService hostTerminalService;
|
||||
|
||||
@Override
|
||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||
registry.addHandler(new WebSocketHandler1(), "/orion/keep-alive/host/terminal")
|
||||
.addInterceptors(userHandshakeInterceptor)
|
||||
.setAllowedOrigins("*");
|
||||
System.out.println("123");
|
||||
}
|
||||
|
||||
static class WebSocketHandler1 implements WebSocketHandler {
|
||||
|
||||
@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() {
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
|
||||
// 获取 token
|
||||
String token = Urls.getUrlSource(request.getURI().getPath());
|
||||
log.info("TerminalInterceptor-beforeHandshake start token: {}", token);
|
||||
// 获取连接数据
|
||||
HostTerminalAccessDTO access = hostTerminalService.getAccessInfoByToken(token);
|
||||
if (access == null) {
|
||||
log.error("TerminalInterceptor-beforeHandshake absent token: {}", token);
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 获取主机终端连接 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 userId userId
|
||||
* @return session
|
||||
*/
|
||||
String getHostAccessToken(Long hostId, Long userId);
|
||||
|
||||
/**
|
||||
* 通过 token 获取主机终端连接信息
|
||||
*
|
||||
* @param token token
|
||||
* @return config
|
||||
*/
|
||||
HostSshConnectDTO getConnectInfoByToken(String token);
|
||||
HostTerminalConnectDTO getTerminalConnectInfo(Long userId, Long hostId);
|
||||
|
||||
/**
|
||||
* 使用默认配置打开主机会话
|
||||
@@ -43,6 +52,6 @@ public interface HostTerminalService {
|
||||
* @param conn conn
|
||||
* @return session
|
||||
*/
|
||||
SessionStore openSessionStore(HostSshConnectDTO conn);
|
||||
SessionStore openSessionStore(HostTerminalConnectDTO conn);
|
||||
|
||||
}
|
||||
|
||||
@@ -6,13 +6,11 @@ import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.net.host.SessionHolder;
|
||||
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.ErrorMessage;
|
||||
import com.orion.ops.framework.common.utils.CryptoUtils;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
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.HostIdentityDAO;
|
||||
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.HostIdentityDO;
|
||||
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.request.host.HostConnectLogCreateRequest;
|
||||
import com.orion.ops.module.asset.enums.*;
|
||||
import com.orion.ops.module.asset.entity.dto.HostTerminalAccessDTO;
|
||||
import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO;
|
||||
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.extra.model.HostSshExtraModel;
|
||||
import com.orion.ops.module.asset.service.HostConfigService;
|
||||
@@ -79,8 +80,34 @@ public class HostTerminalServiceImpl implements HostTerminalService {
|
||||
private SystemUserApi systemUserApi;
|
||||
|
||||
@Override
|
||||
public String getHostAccessToken(Long hostId, Long userId) {
|
||||
log.info("HostConnectService.getHostAccessToken hostId: {}, userId: {}", hostId, userId);
|
||||
public String getHostTerminalAccessToken(Long 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);
|
||||
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.setToken(token);
|
||||
// 设置缓存
|
||||
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);
|
||||
connect.setToken(UUIds.random15());
|
||||
return connect;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,13 +159,13 @@ public class HostTerminalServiceImpl implements HostTerminalService {
|
||||
HostSshConfigModel model = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
|
||||
Valid.notNull(model, ErrorMessage.CONFIG_ABSENT);
|
||||
// 获取配置
|
||||
HostSshConnectDTO connect = this.getHostConnectInfo(host, model, null);
|
||||
HostTerminalConnectDTO connect = this.getHostConnectInfo(host, model, null);
|
||||
// 打开连接
|
||||
return this.openSessionStore(connect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionStore openSessionStore(HostSshConnectDTO conn) {
|
||||
public SessionStore openSessionStore(HostTerminalConnectDTO conn) {
|
||||
Long hostId = conn.getHostId();
|
||||
String address = conn.getHostAddress();
|
||||
String username = conn.getUsername();
|
||||
@@ -212,9 +223,9 @@ public class HostTerminalServiceImpl implements HostTerminalService {
|
||||
* @param extra extra
|
||||
* @return session
|
||||
*/
|
||||
private HostSshConnectDTO getHostConnectInfo(HostDO host,
|
||||
HostSshConfigModel config,
|
||||
HostSshExtraModel extra) {
|
||||
private HostTerminalConnectDTO getHostConnectInfo(HostDO host,
|
||||
HostSshConfigModel config,
|
||||
HostSshExtraModel extra) {
|
||||
// 获取认证方式
|
||||
HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType());
|
||||
HostExtraSshAuthTypeEnum extraAuthType = Optional.ofNullable(extra)
|
||||
@@ -235,7 +246,7 @@ public class HostTerminalServiceImpl implements HostTerminalService {
|
||||
}
|
||||
Long keyId = null;
|
||||
// 填充认证信息
|
||||
HostSshConnectDTO conn = new HostSshConnectDTO();
|
||||
HostTerminalConnectDTO conn = new HostTerminalConnectDTO();
|
||||
conn.setHostId(host.getId());
|
||||
conn.setHostName(host.getName());
|
||||
conn.setHostAddress(host.getAddress());
|
||||
|
||||
Reference in New Issue
Block a user