feat: 获取终端 accessToken.
This commit is contained in:
@@ -50,7 +50,7 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public HttpWrapper<?> defaultExceptionHandler(Exception ex) {
|
||||
log.error("defaultExceptionHandler", ex);
|
||||
return ErrorCode.INTERNAL_SERVER_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.INTERNAL_SERVER_ERROR.wrapper();
|
||||
}
|
||||
|
||||
// -------------------- http 异常 --------------------
|
||||
@@ -98,7 +98,7 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(value = MaxUploadSizeExceededException.class)
|
||||
public HttpWrapper<?> maxUploadSizeExceededExceptionHandler(MaxUploadSizeExceededException ex) {
|
||||
log.error("maxUploadSizeExceededExceptionHandler", ex);
|
||||
return ErrorCode.PAYLOAD_TOO_LARGE.wrapper(ex.getMessage());
|
||||
return ErrorCode.PAYLOAD_TOO_LARGE.wrapper();
|
||||
}
|
||||
|
||||
// -------------------- 框架异常 --------------------
|
||||
@@ -132,7 +132,7 @@ public class GlobalExceptionHandler {
|
||||
})
|
||||
public HttpWrapper<?> timeoutExceptionHandler(Exception ex) {
|
||||
log.error("timeoutExceptionHandler", ex);
|
||||
return ErrorCode.REQUEST_TIMEOUT.wrapper(ex.getMessage());
|
||||
return ErrorCode.REQUEST_TIMEOUT.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {
|
||||
@@ -142,7 +142,7 @@ public class GlobalExceptionHandler {
|
||||
})
|
||||
public HttpWrapper<?> interruptExceptionHandler(Exception ex) {
|
||||
log.error("interruptExceptionHandler", ex);
|
||||
return ErrorCode.INTERRUPT_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.INTERRUPT_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {
|
||||
@@ -151,7 +151,7 @@ public class GlobalExceptionHandler {
|
||||
})
|
||||
public HttpWrapper<?> ioExceptionHandler(Exception ex) {
|
||||
log.error("ioExceptionHandler", ex);
|
||||
return ErrorCode.IO_EXCEPTION.wrapper(ex.getMessage());
|
||||
return ErrorCode.IO_EXCEPTION.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = SQLException.class)
|
||||
@@ -178,7 +178,7 @@ public class GlobalExceptionHandler {
|
||||
})
|
||||
public HttpWrapper<?> sftpExceptionHandler(Exception ex) {
|
||||
log.error("sftpExceptionHandler", ex);
|
||||
return ErrorCode.SFTP_EXCEPTION.wrapper(ex.getMessage());
|
||||
return ErrorCode.SFTP_EXCEPTION.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = ParseRuntimeException.class)
|
||||
@@ -186,22 +186,22 @@ public class GlobalExceptionHandler {
|
||||
log.error("parseExceptionHandler", ex);
|
||||
if (Exceptions.isCausedBy(ex, EncryptedDocumentException.class)) {
|
||||
// excel 密码错误
|
||||
return ErrorCode.EXCEL_PASSWORD_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.EXCEL_PASSWORD_ERROR.wrapper();
|
||||
} else {
|
||||
return ErrorCode.PASER_FAILED.wrapper(ex.getMessage());
|
||||
return ErrorCode.PASER_FAILED.wrapper();
|
||||
}
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = EncryptException.class)
|
||||
public HttpWrapper<?> encryptExceptionHandler(Exception ex) {
|
||||
log.error("encryptExceptionHandler", ex);
|
||||
return ErrorCode.ENCRYPT_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.ENCRYPT_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = DecryptException.class)
|
||||
public HttpWrapper<?> decryptExceptionHandler(Exception ex) {
|
||||
log.error("decryptExceptionHandler", ex);
|
||||
return ErrorCode.DECRYPT_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.DECRYPT_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {HttpRequestException.class})
|
||||
@@ -213,7 +213,7 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(value = VcsException.class)
|
||||
public HttpWrapper<?> vcsExceptionHandler(Exception ex) {
|
||||
log.error("vcsExceptionHandler", ex);
|
||||
return ErrorCode.VCS_OPETATOR_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.VCS_OPETATOR_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {
|
||||
@@ -222,30 +222,31 @@ public class GlobalExceptionHandler {
|
||||
})
|
||||
public HttpWrapper<?> taskExceptionHandler(Exception ex) {
|
||||
log.error("taskExceptionHandler", ex);
|
||||
return ErrorCode.TASK_EXECUTE_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.TASK_EXECUTE_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = ConnectionRuntimeException.class)
|
||||
public HttpWrapper<?> connectionExceptionHandler(Exception ex) {
|
||||
log.error("connectionExceptionHandler", ex);
|
||||
return ErrorCode.CONNECT_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.CONNECT_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = UnsafeException.class)
|
||||
public HttpWrapper<?> unsafeExceptionHandler(Exception ex) {
|
||||
log.error("unsafeExceptionHandler", ex);
|
||||
return ErrorCode.UNSAFE_OPERATOR.wrapper(ex.getMessage());
|
||||
return ErrorCode.UNSAFE_OPERATOR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = LogException.class)
|
||||
public HttpWrapper<?> logExceptionHandler(LogException ex) {
|
||||
log.error("logExceptionHandler", ex);
|
||||
return ErrorCode.INTERNAL_SERVER_ERROR.wrapper(ex.getMessage());
|
||||
return ErrorCode.INTERNAL_SERVER_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = ParseCronException.class)
|
||||
public HttpWrapper<?> parseCronExceptionHandler(ParseCronException ex) {
|
||||
return ErrorCode.EXPRESSION_ERROR.wrapper(ex.getMessage());
|
||||
log.error("parseCronExceptionHandler", ex);
|
||||
return ErrorCode.EXPRESSION_ERROR.wrapper();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = CodeArgumentException.class)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
### 获取主机终端连接 token
|
||||
POST {{baseUrl}}/asset/host-terminal/access
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"hostId": 1
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
@@ -0,0 +1,49 @@
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 主机终端 api
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-9-20 11:55
|
||||
*/
|
||||
@Tag(name = "asset - 主机终端服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/host-terminal")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class HostTerminalController {
|
||||
|
||||
@Resource
|
||||
private HostTerminalService hostTerminalService;
|
||||
|
||||
@OperatorLog(HostTerminalOperatorType.ACCESS)
|
||||
@PostMapping("/access")
|
||||
@Operation(summary = "获取主机终端连接 token")
|
||||
@PreAuthorize("@ss.hasPermission('asset:host-terminal:access')")
|
||||
public String getHostAccessToken(@Validated @RequestBody HostTerminalConnectRequest request) {
|
||||
return hostTerminalService.getHostAccessToken(request.getHostId(), SecurityUtils.getLoginUserId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
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 java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 主机终端服务缓存 key
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/12/27 18:13
|
||||
*/
|
||||
public interface HostTerminalCacheKeyDefine {
|
||||
|
||||
CacheKeyDefine HOST_TERMINAL_CONNECT = new CacheKeyBuilder()
|
||||
.key("host:terminal:connect:{}")
|
||||
.desc("主机终端连接信息 ${token}")
|
||||
.type(HostSshConnectDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(3, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.orion.ops.module.asset.define.operator;
|
||||
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.Module;
|
||||
import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
|
||||
|
||||
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.L;
|
||||
|
||||
/**
|
||||
* 主机终端 操作日志类型
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/10/10 17:30
|
||||
*/
|
||||
@Module("asset:host-terminal")
|
||||
public class HostTerminalOperatorType extends InitializingOperatorTypes {
|
||||
|
||||
public static final String ACCESS = "host-terminal:access";
|
||||
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(L, ACCESS, "连接主机终端 <sb>${hostName}</sb>"),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orion.ops.module.asset.entity.dto;
|
||||
|
||||
import com.orion.ops.module.asset.entity.domain.HostKeyDO;
|
||||
import com.orion.ops.module.asset.enums.HostSshAuthTypeEnum;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.Desensitize;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.DesensitizeObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -19,12 +19,22 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@DesensitizeObject
|
||||
@Schema(name = "HostSshConnectDTO", description = "主机连接参数")
|
||||
public class HostSshConnectDTO {
|
||||
|
||||
@Schema(description = "token")
|
||||
private String token;
|
||||
|
||||
@Schema(description = "userId")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "hostId")
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "hostName")
|
||||
private String hostName;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
private String address;
|
||||
|
||||
@@ -34,19 +44,26 @@ public class HostSshConnectDTO {
|
||||
@Schema(description = "超时时间")
|
||||
private Integer timeout;
|
||||
|
||||
@Schema(description = "认证方式")
|
||||
private HostSshAuthTypeEnum authType;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Desensitize(toEmpty = true)
|
||||
@Schema(description = "密码")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "主机秘钥")
|
||||
private HostKeyDO key;
|
||||
@Schema(description = "秘钥id")
|
||||
private Long keyId;
|
||||
|
||||
// @Schema(description = "")
|
||||
// private ;
|
||||
@Desensitize(toEmpty = true)
|
||||
@Schema(description = "公钥文本")
|
||||
private String publicKey;
|
||||
|
||||
@Desensitize(toEmpty = true)
|
||||
@Schema(description = "私钥文本")
|
||||
private String privateKey;
|
||||
|
||||
@Desensitize(toEmpty = true)
|
||||
@Schema(description = "私钥密码")
|
||||
private String privateKeyPassword;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.net.host.SessionStore;
|
||||
|
||||
/**
|
||||
* 主机连接服务
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/12/26 14:22
|
||||
*/
|
||||
public interface HostConnectService {
|
||||
|
||||
/**
|
||||
* 打开主机会话
|
||||
* 鉴权并且读取用户配置
|
||||
*
|
||||
* @param hostId hostId
|
||||
* @param userId userId
|
||||
* @return session
|
||||
*/
|
||||
SessionStore openSessionStore(Long hostId, Long userId);
|
||||
|
||||
/**
|
||||
* 打开主机会话
|
||||
* 使用默认配置 不鉴权
|
||||
*
|
||||
* @param hostId hostId
|
||||
* @return session
|
||||
*/
|
||||
SessionStore openSessionStore(Long hostId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.net.host.SessionStore;
|
||||
import com.orion.ops.module.asset.entity.dto.HostSshConnectDTO;
|
||||
|
||||
/**
|
||||
* 主机终端服务
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/12/26 14:22
|
||||
*/
|
||||
public interface HostTerminalService {
|
||||
|
||||
/**
|
||||
* 获取主机终端连接 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);
|
||||
|
||||
/**
|
||||
* 使用默认配置打开主机会话
|
||||
*
|
||||
* @param hostId hostId
|
||||
* @return session
|
||||
*/
|
||||
SessionStore openSessionStore(Long hostId);
|
||||
|
||||
/**
|
||||
* 打开主机会话
|
||||
*
|
||||
* @param conn conn
|
||||
* @return session
|
||||
*/
|
||||
SessionStore openSessionStore(HostSshConnectDTO conn);
|
||||
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.orion.lang.exception.AuthenticationException;
|
||||
import com.orion.lang.id.UUIds;
|
||||
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.dao.HostDAO;
|
||||
import com.orion.ops.module.asset.dao.HostIdentityDAO;
|
||||
import com.orion.ops.module.asset.dao.HostKeyDAO;
|
||||
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;
|
||||
@@ -23,10 +27,12 @@ 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;
|
||||
import com.orion.ops.module.asset.service.HostConnectService;
|
||||
import com.orion.ops.module.asset.service.HostConnectLogService;
|
||||
import com.orion.ops.module.asset.service.HostExtraService;
|
||||
import com.orion.ops.module.asset.service.HostTerminalService;
|
||||
import com.orion.ops.module.infra.api.DataPermissionApi;
|
||||
import com.orion.ops.module.infra.api.SystemUserApi;
|
||||
import com.orion.ops.module.infra.entity.dto.user.SystemUserDTO;
|
||||
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -44,7 +50,7 @@ import java.util.Optional;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class HostConnectServiceImpl implements HostConnectService {
|
||||
public class HostTerminalServiceImpl implements HostTerminalService {
|
||||
|
||||
@Resource
|
||||
private HostConfigService hostConfigService;
|
||||
@@ -55,6 +61,9 @@ public class HostConnectServiceImpl implements HostConnectService {
|
||||
@Resource
|
||||
private AssetAuthorizedDataServiceImpl assetAuthorizedDataService;
|
||||
|
||||
@Resource
|
||||
private HostConnectLogService hostConnectLogService;
|
||||
|
||||
@Resource
|
||||
private HostDAO hostDAO;
|
||||
|
||||
@@ -71,11 +80,14 @@ public class HostConnectServiceImpl implements HostConnectService {
|
||||
private SystemUserApi systemUserApi;
|
||||
|
||||
@Override
|
||||
public SessionStore openSessionStore(Long hostId, Long userId) {
|
||||
log.info("HostConnectService.openSessionStore-withUser hostId: {}, userId: {}", hostId, userId);
|
||||
public String getHostAccessToken(Long hostId, Long userId) {
|
||||
log.info("HostConnectService.getHostAccessToken hostId: {}, userId: {}", hostId, userId);
|
||||
// 查询主机
|
||||
HostDO host = hostDAO.selectById(hostId);
|
||||
Valid.notNull(host, ErrorMessage.HOST_ABSENT);
|
||||
// 查询用户
|
||||
SystemUserDTO user = systemUserApi.getUserById(userId);
|
||||
Valid.notNull(user, ErrorMessage.USER_ABSENT);
|
||||
// 查询主机配置
|
||||
HostSshConfigModel config = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
|
||||
Valid.notNull(config, ErrorMessage.CONFIG_ABSENT);
|
||||
@@ -104,8 +116,24 @@ public class HostConnectServiceImpl implements HostConnectService {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 连接
|
||||
return this.openSessionStoreWithHost(host, config, extra);
|
||||
String token = UUIds.random32();
|
||||
// 获取连接配置
|
||||
HostSshConnectDTO connect = this.getHostConnectInfo(host, config, extra);
|
||||
connect.setUserId(userId);
|
||||
connect.setUsername(user.getUsername());
|
||||
connect.setToken(token);
|
||||
// 设置缓存
|
||||
String key = HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT.format(token);
|
||||
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.HOST_TERMINAL_CONNECT, connect);
|
||||
// 设置日志参数
|
||||
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
|
||||
@@ -115,102 +143,36 @@ public class HostConnectServiceImpl implements HostConnectService {
|
||||
HostDO host = hostDAO.selectById(hostId);
|
||||
Valid.notNull(host, ErrorMessage.HOST_ABSENT);
|
||||
// 查询主机配置
|
||||
HostSshConfigModel config = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
|
||||
Valid.notNull(config, ErrorMessage.CONFIG_ABSENT);
|
||||
// 连接
|
||||
return this.openSessionStoreWithHost(host, config, null);
|
||||
HostSshConfigModel model = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
|
||||
Valid.notNull(model, ErrorMessage.CONFIG_ABSENT);
|
||||
// 获取配置
|
||||
HostSshConnectDTO connect = this.getHostConnectInfo(host, model, null);
|
||||
// 打开连接
|
||||
return this.openSessionStore(connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主机会话
|
||||
*
|
||||
* @param host host
|
||||
* @param config config
|
||||
* @param extra extra
|
||||
* @return session
|
||||
*/
|
||||
private SessionStore openSessionStoreWithHost(HostDO host,
|
||||
HostSshConfigModel config,
|
||||
HostSshExtraModel extra) {
|
||||
// 获取认证方式
|
||||
HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType());
|
||||
HostExtraSshAuthTypeEnum extraAuthType = Optional.ofNullable(extra)
|
||||
.map(HostSshExtraModel::getAuthType)
|
||||
.map(HostExtraSshAuthTypeEnum::of)
|
||||
.orElse(HostExtraSshAuthTypeEnum.DEFAULT);
|
||||
if (HostExtraSshAuthTypeEnum.CUSTOM_KEY.equals(extraAuthType)) {
|
||||
// 自定义秘钥
|
||||
authType = HostSshAuthTypeEnum.KEY;
|
||||
config.setKeyId(extra.getKeyId());
|
||||
if (extra.getUsername() != null) {
|
||||
config.setUsername(extra.getUsername());
|
||||
}
|
||||
} else if (HostExtraSshAuthTypeEnum.CUSTOM_IDENTITY.equals(extraAuthType)) {
|
||||
// 自定义身份
|
||||
authType = HostSshAuthTypeEnum.IDENTITY;
|
||||
config.setIdentityId(extra.getIdentityId());
|
||||
}
|
||||
// 填充认证信息
|
||||
HostSshConnectDTO conn = new HostSshConnectDTO();
|
||||
conn.setHostId(host.getId());
|
||||
conn.setAddress(host.getAddress());
|
||||
conn.setPort(config.getPort());
|
||||
conn.setTimeout(config.getConnectTimeout());
|
||||
conn.setAuthType(authType);
|
||||
conn.setUsername(config.getUsername());
|
||||
// 填充身份信息
|
||||
if (HostSshAuthTypeEnum.PASSWORD.equals(authType)) {
|
||||
conn.setPassword(config.getPassword());
|
||||
} else if (HostSshAuthTypeEnum.KEY.equals(authType)) {
|
||||
// 秘钥认证
|
||||
HostKeyDO key = hostKeyDAO.selectById(config.getKeyId());
|
||||
Valid.notNull(key, ErrorMessage.KEY_ABSENT);
|
||||
conn.setKey(key);
|
||||
} else if (HostSshAuthTypeEnum.IDENTITY.equals(authType)) {
|
||||
// 身份认证
|
||||
HostIdentityDO identity = hostIdentityDAO.selectById(config.getIdentityId());
|
||||
Valid.notNull(identity, ErrorMessage.IDENTITY_ABSENT);
|
||||
if (identity.getKeyId() != null) {
|
||||
// 秘钥认证
|
||||
HostKeyDO key = hostKeyDAO.selectById(config.getKeyId());
|
||||
Valid.notNull(key, ErrorMessage.KEY_ABSENT);
|
||||
conn.setKey(key);
|
||||
}
|
||||
conn.setUsername(identity.getUsername());
|
||||
conn.setPassword(identity.getPassword());
|
||||
}
|
||||
// 连接
|
||||
return this.openSessionStoreWithConfig(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主机会话
|
||||
*
|
||||
* @param conn conn
|
||||
* @return session
|
||||
*/
|
||||
private SessionStore openSessionStoreWithConfig(HostSshConnectDTO conn) {
|
||||
@Override
|
||||
public SessionStore openSessionStore(HostSshConnectDTO conn) {
|
||||
Long hostId = conn.getHostId();
|
||||
String address = conn.getAddress();
|
||||
String username = conn.getUsername();
|
||||
log.info("HostConnectService-openSessionStore-start hostId: {}, address: {}, username: {}", hostId, address, username);
|
||||
try {
|
||||
SessionHolder sessionHolder = new SessionHolder();
|
||||
HostKeyDO key = conn.getKey();
|
||||
final boolean useKey = key != null;
|
||||
final boolean useKey = conn.getKeyId() != null;
|
||||
// 使用秘钥认证
|
||||
if (useKey) {
|
||||
// 加载秘钥
|
||||
String publicKey = Optional.ofNullable(key.getPublicKey())
|
||||
String publicKey = Optional.ofNullable(conn.getPublicKey())
|
||||
.map(CryptoUtils::decryptAsString)
|
||||
.orElse(null);
|
||||
String privateKey = Optional.ofNullable(key.getPrivateKey())
|
||||
String privateKey = Optional.ofNullable(conn.getPrivateKey())
|
||||
.map(CryptoUtils::decryptAsString)
|
||||
.orElse(null);
|
||||
String password = Optional.ofNullable(key.getPassword())
|
||||
String password = Optional.ofNullable(conn.getPrivateKeyPassword())
|
||||
.map(CryptoUtils::decryptAsString)
|
||||
.orElse(null);
|
||||
sessionHolder.addIdentityValue(String.valueOf(key.getId()),
|
||||
sessionHolder.addIdentityValue(String.valueOf(conn.getKeyId()),
|
||||
privateKey,
|
||||
publicKey,
|
||||
password);
|
||||
@@ -240,4 +202,68 @@ public class HostConnectServiceImpl implements HostConnectService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主机会话连接配置
|
||||
*
|
||||
* @param host host
|
||||
* @param config config
|
||||
* @param extra extra
|
||||
* @return session
|
||||
*/
|
||||
private HostSshConnectDTO getHostConnectInfo(HostDO host,
|
||||
HostSshConfigModel config,
|
||||
HostSshExtraModel extra) {
|
||||
// 获取认证方式
|
||||
HostSshAuthTypeEnum authType = HostSshAuthTypeEnum.of(config.getAuthType());
|
||||
HostExtraSshAuthTypeEnum extraAuthType = Optional.ofNullable(extra)
|
||||
.map(HostSshExtraModel::getAuthType)
|
||||
.map(HostExtraSshAuthTypeEnum::of)
|
||||
.orElse(HostExtraSshAuthTypeEnum.DEFAULT);
|
||||
if (HostExtraSshAuthTypeEnum.CUSTOM_KEY.equals(extraAuthType)) {
|
||||
// 自定义秘钥
|
||||
authType = HostSshAuthTypeEnum.KEY;
|
||||
config.setKeyId(extra.getKeyId());
|
||||
if (extra.getUsername() != null) {
|
||||
config.setUsername(extra.getUsername());
|
||||
}
|
||||
} else if (HostExtraSshAuthTypeEnum.CUSTOM_IDENTITY.equals(extraAuthType)) {
|
||||
// 自定义身份
|
||||
authType = HostSshAuthTypeEnum.IDENTITY;
|
||||
config.setIdentityId(extra.getIdentityId());
|
||||
}
|
||||
Long keyId = null;
|
||||
// 填充认证信息
|
||||
HostSshConnectDTO conn = new HostSshConnectDTO();
|
||||
conn.setHostId(host.getId());
|
||||
conn.setHostName(host.getName());
|
||||
conn.setAddress(host.getAddress());
|
||||
conn.setPort(config.getPort());
|
||||
conn.setTimeout(config.getConnectTimeout());
|
||||
conn.setUsername(config.getUsername());
|
||||
// 填充身份信息
|
||||
if (HostSshAuthTypeEnum.PASSWORD.equals(authType)) {
|
||||
conn.setPassword(config.getPassword());
|
||||
} else if (HostSshAuthTypeEnum.KEY.equals(authType)) {
|
||||
// 秘钥认证
|
||||
keyId = config.getKeyId();
|
||||
} else if (HostSshAuthTypeEnum.IDENTITY.equals(authType)) {
|
||||
// 身份认证
|
||||
HostIdentityDO identity = hostIdentityDAO.selectById(config.getIdentityId());
|
||||
Valid.notNull(identity, ErrorMessage.IDENTITY_ABSENT);
|
||||
keyId = identity.getKeyId();
|
||||
conn.setUsername(identity.getUsername());
|
||||
conn.setPassword(identity.getPassword());
|
||||
}
|
||||
// 设置秘钥信息
|
||||
if (keyId != null) {
|
||||
HostKeyDO key = hostKeyDAO.selectById(keyId);
|
||||
Valid.notNull(key, ErrorMessage.KEY_ABSENT);
|
||||
conn.setPublicKey(key.getPublicKey());
|
||||
conn.setPrivateKey(key.getPrivateKey());
|
||||
conn.setPrivateKeyPassword(key.getPassword());
|
||||
}
|
||||
// 连接
|
||||
return conn;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -65,7 +65,7 @@ INSERT INTO `system_menu` VALUES (106, 105, '查询字典配置值', 'infra:dict
|
||||
INSERT INTO `system_menu` VALUES (107, 105, '创建字典配置值', 'infra:dict-value:create', 3, 220, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-17 11:38:18', '2023-10-27 01:16:10', NULL, '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (108, 105, '修改字典配置值', 'infra:dict-value:update', 3, 230, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-17 11:38:18', '2023-10-27 01:16:10', NULL, '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (109, 105, '删除字典配置值', 'infra:dict-value:delete', 3, 240, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-17 11:38:18', '2023-10-27 01:16:10', NULL, '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (120, 97, '查询字典配置项', 'infra:dict-key:create', 3, 100, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-20 11:27:12', '2023-10-27 01:16:10', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (120, 97, '查询字典配置项', 'infra:dict-key:query', 3, 100, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-20 11:27:12', '2023-10-27 01:16:10', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (121, 97, '刷新缓存', 'infra:dict-key:management:refresh-cache', 3, 140, 1, 1, 1, 0, NULL, NULL, NULL, '2023-10-27 15:50:04', '2023-12-27 12:40:12', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (122, 5, '操作日志', NULL, 2, 30, 1, 1, 1, 0, 'IconCalendarClock', NULL, 'userOperatorLog', '2023-11-01 14:09:36', '2023-11-01 14:09:36', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (123, 122, '查询操作日志', 'infra:operator-log:query', 3, 10, 1, 1, 1, 0, NULL, NULL, NULL, '2023-11-02 11:22:54', '2023-11-02 11:22:54', '1', '1', 0);
|
||||
|
||||
Reference in New Issue
Block a user