Compare commits
No commits in common. "7a995e159fe3dfb434f71c406318e4effa22b01a" and "2f3a2ae28fd2fe42998c3bbccfc77e3b019afda3" have entirely different histories.
7a995e159f
...
2f3a2ae28f
@ -99,9 +99,9 @@ public class SecretKeyController {
|
||||
return success(BeanUtils.toBean(pageResult, SecretKeyVO.class));
|
||||
}
|
||||
|
||||
// @GetMapping("/download")
|
||||
// @Operation(summary = "下载密钥文件")
|
||||
// public ResponseEntity<InputStreamResource> downloadSecretFile(@RequestParam("id") Long id) {
|
||||
// return secretKeyService.downloadSecretFile(id);
|
||||
// }
|
||||
@GetMapping("/download")
|
||||
@Operation(summary = "下载密钥文件")
|
||||
public ResponseEntity<InputStreamResource> downloadSecretFile(@RequestParam("id") Long id) {
|
||||
return secretKeyService.downloadSecretFile(id);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,12 @@ public class SecretKeyVO extends PageParam {
|
||||
@Schema(description = "密钥描述", example = "用于加密敏感数据的密钥")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "存储路径(本地上传文件路径)", example = "/data/secret_keys/")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "文件名", example = "key.pem")
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "密钥密码", example = "******")
|
||||
private String password;
|
||||
|
||||
@ -38,11 +44,4 @@ public class SecretKeyVO extends PageParam {
|
||||
|
||||
@Schema(description = "关联的机器ID列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 2048]")
|
||||
private List<Long> machineInfoIds;
|
||||
|
||||
@Schema(description = "私钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "******")
|
||||
private String private_key;
|
||||
|
||||
@Schema(description = "公钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "******")
|
||||
private String public_key;
|
||||
|
||||
}
|
||||
|
@ -28,17 +28,14 @@ public class SecretKeyDO extends BaseDO {
|
||||
@TableField(value = "description")
|
||||
private String description;
|
||||
|
||||
//oss存储路径
|
||||
@TableField(value = "path")
|
||||
private String path;
|
||||
|
||||
@TableField
|
||||
private String fileName;
|
||||
|
||||
//密钥密码
|
||||
@TableField(value = "password")
|
||||
private String password;
|
||||
|
||||
@TableField(value = "public_key")
|
||||
private String public_key;
|
||||
|
||||
|
||||
@TableField(value = "private_key")
|
||||
private String private_key;
|
||||
|
||||
|
||||
}
|
||||
|
@ -32,13 +32,6 @@ public interface MachineInfoService {
|
||||
|
||||
void deleteMachineInfo(Long machineInfoId);
|
||||
|
||||
/**
|
||||
* 获取绑定的密钥
|
||||
* @param secretKeyId 密钥id
|
||||
* @return 绑定的机器列表
|
||||
*/
|
||||
List<MachineInfoDO>selectBindMachineBySecretKey(Long secretKeyId);
|
||||
|
||||
|
||||
/**
|
||||
* 测试机器连接
|
||||
|
@ -27,8 +27,10 @@ public interface SecretKeyService {
|
||||
|
||||
void unbindMachine(@Valid SecretKeyVO secretKeyVO);
|
||||
|
||||
ResponseEntity<InputStreamResource> downloadSecretFile(Long id);
|
||||
|
||||
List<MachineInfoDO> getBindMachine(Long secretKeyId);
|
||||
|
||||
// String getKeyContent(Long secretKeyId);
|
||||
String getKeyContent(Long secretKeyId);
|
||||
}
|
||||
|
||||
|
@ -107,11 +107,6 @@ public class MachineInfoServiceImpl implements MachineInfoService {
|
||||
machineInfoMapper.deleteById(machineInfoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MachineInfoDO> selectBindMachineBySecretKey(Long secretKeyId) {
|
||||
return machineInfoMapper.selectBindMachineBySecretKey(secretKeyId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean testConnection(Long id) {
|
||||
|
@ -5,6 +5,7 @@ import cd.casic.framework.commons.util.object.BeanUtils;
|
||||
import cd.casic.module.machine.controller.vo.SecretKeyVO;
|
||||
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
|
||||
import cd.casic.module.machine.dal.dataobject.SecretKeyDO;
|
||||
import cd.casic.module.machine.dal.mysql.MachineInfoMapper;
|
||||
import cd.casic.module.machine.dal.mysql.SecretKeyMapper;
|
||||
import cd.casic.module.machine.service.MachineInfoService;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
@ -13,9 +14,18 @@ import cd.casic.module.machine.utils.AliYunOssClient;
|
||||
import cd.casic.module.machine.service.SecretKeyService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
|
||||
@ -24,20 +34,21 @@ import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
|
||||
/**
|
||||
* 密钥服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("secretKeyService")
|
||||
public class SecretKeyServiceImpl implements SecretKeyService {
|
||||
|
||||
@Resource
|
||||
private MachineInfoService machineInfoService;
|
||||
|
||||
@Resource
|
||||
private AliYunOssClient aliYunOssClient;
|
||||
|
||||
@Resource
|
||||
private SecretKeyMapper secretKeyMapper;
|
||||
|
||||
@Override
|
||||
public void deleteSecretKey(Long id) {
|
||||
validateSecretKeyExists(id);
|
||||
secretKeyMapper.deleteById(id);
|
||||
}
|
||||
@Resource
|
||||
private MachineInfoMapper machineInfoMapper;
|
||||
|
||||
@Override
|
||||
public SecretKeyVO getSecretKey(Long id) {
|
||||
@ -45,30 +56,68 @@ public class SecretKeyServiceImpl implements SecretKeyService {
|
||||
return BeanUtils.toBean(secretKeyDO, SecretKeyVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSecretKey(Long id) {
|
||||
validateSecretKeyExists(id);
|
||||
secretKeyMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindMachine(SecretKeyVO secretKeyVO) {
|
||||
machineInfoService.bindingSecretKey(secretKeyVO.getMachineInfoIds(),null);
|
||||
machineInfoService.bindingSecretKey(secretKeyVO.getMachineInfoIds(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InputStreamResource> downloadSecretFile(Long id) {
|
||||
// 获取私钥内容
|
||||
String keyContent = getKeyContent(id);
|
||||
if (keyContent == null || keyContent.isEmpty()) {
|
||||
throw exception(SECRET_KEY_NULL);
|
||||
}
|
||||
// 将字符串转换为输入流
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(keyContent.getBytes(StandardCharsets.UTF_8));
|
||||
// 设置响应头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=private_key.pem");
|
||||
headers.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream");
|
||||
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(keyContent.getBytes(StandardCharsets.UTF_8).length));
|
||||
// 返回带有文件流的响应实体
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.body(new InputStreamResource(inputStream));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MachineInfoDO> getBindMachine(Long secretKeyId) {
|
||||
return machineInfoService.selectBindMachineBySecretKey(secretKeyId);
|
||||
return machineInfoMapper.selectBindMachineBySecretKey(secretKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createSecretKey(SecretKeyVO secretKeyVO) {
|
||||
validateSecretKeyAdd(secretKeyVO);
|
||||
String localPath = secretKeyVO.getPath();
|
||||
//将反斜杠替换为双反斜杠(Windows路径转义)
|
||||
localPath = localPath.replace("\\", "\\\\");
|
||||
String ossPath = upLoadSecretKey(localPath);
|
||||
//检查得到的oss路径是否为空
|
||||
validateSecretKeyPath(ossPath);
|
||||
secretKeyVO.setPath(ossPath);
|
||||
SecretKeyDO secretKeyDO = BeanUtils.toBean(secretKeyVO, SecretKeyDO.class);
|
||||
secretKeyMapper.insert(secretKeyDO);
|
||||
return secretKeyDO.getId();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSecretKey(SecretKeyVO secretKeyVO) {
|
||||
SecretKeyDO secretKeyDO = validateSecretKeyExists(secretKeyVO.getId());
|
||||
BeanUtils.copyProperties(secretKeyVO, secretKeyDO);
|
||||
//路径改变==改变密钥
|
||||
if (!secretKeyDO.getPath().equals(secretKeyVO.getPath())) {
|
||||
String ossPath = upLoadSecretKey(secretKeyVO.getPath());
|
||||
BeanUtils.copyProperties(secretKeyVO, secretKeyDO);
|
||||
secretKeyDO.setPath(ossPath);
|
||||
} else {
|
||||
BeanUtils.copyProperties(secretKeyVO, secretKeyDO);
|
||||
}
|
||||
secretKeyMapper.updateById(secretKeyDO);
|
||||
}
|
||||
|
||||
@ -81,7 +130,24 @@ public class SecretKeyServiceImpl implements SecretKeyService {
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteSecretKeyList(List<Long> ids) {
|
||||
machineInfoService.bindingSecretKey(ids,null);
|
||||
ids.forEach(
|
||||
secretKeyId -> {
|
||||
SecretKeyDO secretKeyDO = validateSecretKeyExists(secretKeyId);
|
||||
if (secretKeyDO.getPath() != null && !secretKeyDO.getPath().isEmpty()) {
|
||||
try {
|
||||
//文件名
|
||||
//删除子目录文件,需要在前面加上根目录文件路径
|
||||
String fileName = secretKeyDO.getPath().substring(secretKeyDO.getPath().lastIndexOf("/") + 1);
|
||||
aliYunOssClient.delete(fileName);
|
||||
} catch (Exception e) {
|
||||
throw exception(DELETE_FILE_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//绑定的机器全部设置为空
|
||||
machineInfoService.bindingSecretKey(ids, null);
|
||||
secretKeyMapper.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
@ -90,14 +156,38 @@ public class SecretKeyServiceImpl implements SecretKeyService {
|
||||
return secretKeyMapper.selectPage(secretKeyVO);
|
||||
}
|
||||
|
||||
public String upLoadSecretKey(String localPath) {
|
||||
//使用S3FileClient上传文件
|
||||
aliYunOssClient.init();
|
||||
//传输到指定文件,需要在path前面加上文件路径
|
||||
String path = IdUtil.fastSimpleUUID() + ".txt";
|
||||
//上传文件是从本地上传,这里传的是本地文件地址
|
||||
byte[] content = ResourceUtil.readBytes(localPath);
|
||||
String ossPath;
|
||||
try {
|
||||
ossPath = aliYunOssClient.upload(content, path, "txt");
|
||||
} catch (Exception e) {
|
||||
throw exception(UPLOADING_FILE_FAIL);
|
||||
}
|
||||
return ossPath;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateSecretKeyAdd(SecretKeyVO secretKeyVO) {
|
||||
if (secretKeyVO == null) {
|
||||
throw exception(SECRET_KEY_NULL);
|
||||
}
|
||||
if (secretKeyVO.getPath().isEmpty()) {
|
||||
throw exception(SECRET_KEY_PATH_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateSecretKeyPath(String path) {
|
||||
if (path.isEmpty()) {
|
||||
throw exception(SECRET_KEY_PATH_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
@ -112,4 +202,25 @@ public class SecretKeyServiceImpl implements SecretKeyService {
|
||||
return secretKeyDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyContent(Long secretKeyId) {
|
||||
if (secretKeyId == null) {
|
||||
return null;
|
||||
}
|
||||
SecretKeyVO secretKey = getSecretKey(secretKeyId);
|
||||
byte[] content;
|
||||
try {
|
||||
content = aliYunOssClient.getContent(secretKey.getPath().substring(secretKey.getPath().lastIndexOf("/") + 1));
|
||||
} catch (Exception e) {
|
||||
log.error("读取密钥文件失败", e);
|
||||
throw exception(READ_SECRET_CONTENT_ERROR);
|
||||
}
|
||||
//改为S3FileClient读取
|
||||
InputStream read = new ByteArrayInputStream(content);
|
||||
try {
|
||||
return StreamUtils.copyToString(read, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user