密钥管理接口

This commit is contained in:
liulu 2024-10-29 10:51:24 +08:00
parent be088194cc
commit f7e63fadb9
16 changed files with 147 additions and 44 deletions

View File

@ -32,6 +32,10 @@
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>

View File

@ -3,7 +3,9 @@ package com.sunyard.chsm.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import javax.persistence.Transient;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author liulu
@ -31,4 +33,8 @@ public class KeyInfo {
private LocalDateTime createTime;
private LocalDateTime updateTime;
@Transient
private List<KeyRecord> records;
}

View File

@ -0,0 +1,21 @@
package com.sunyard.chsm.utils;
import java.time.format.DateTimeFormatter;
/**
* @author liulu
* @version V1.0
* @since 2022/12/6
*/
public abstract class DateFormat {
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String HH_MM_SS = "HH:mm:ss";
public static final DateTimeFormatter TIME = DateTimeFormatter.ofPattern(HH_MM_SS);
public static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern(YYYY_MM_DD);
public static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
}

View File

@ -1,16 +0,0 @@
package com.sunyard.chsm.utils;
/**
* @author liulu
* @version V1.0
* @since 2022/12/6
*/
public abstract class DateFormatPattern {
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String HH_MM_SS = "HH:mm:ss";
}

View File

@ -16,7 +16,6 @@ import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
@ -33,13 +32,13 @@ public abstract class JsonUtils {
static {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateFormat.TIME));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateFormat.DATE));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateFormat.DATE_TIME));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateFormat.TIME));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateFormat.DATE));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateFormat.DATE_TIME));
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

View File

@ -111,10 +111,7 @@
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
</dependencies>

View File

@ -5,11 +5,19 @@ import com.sunyard.chsm.dto.KeyInfoDTO;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.service.KeyInfoService;
import com.sunyard.chsm.utils.DateFormat;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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;
import javax.validation.Valid;
/**
* 非对称密钥管理接口
@ -37,5 +45,31 @@ public class KeyInfoAsymController {
return R.data(page);
}
/**
* 密钥备份(文件下载)
*
* @param backup 参数
*/
@PostMapping("/backup")
public ResponseEntity<org.springframework.core.io.Resource> backupKey(@Valid @RequestBody KeyInfoDTO.Backup backup) {
backup.setKeyType(KeyCategory.SYM_KEY.getCode());
byte[] content = keyInfoService.backupKey(backup);
String fileName = String.join("-",
"AsymKey-Backup",
backup.getStartTime().format(DateFormat.DATE),
backup.getEndTime().format(DateFormat.DATE)
);
// 设置下载响应的 headers
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
// 返回带文件内容的响应
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new ByteArrayResource(content));
}
}

View File

@ -5,13 +5,19 @@ import com.sunyard.chsm.dto.KeyInfoDTO;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.service.KeyInfoService;
import com.sunyard.chsm.utils.DateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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;
import javax.validation.Valid;
/**
@ -24,7 +30,7 @@ import javax.validation.Valid;
@RequestMapping("/key/info/sym")
public class KeyInfoSymController {
@Resource
@Autowired
private KeyInfoService keyInfoService;
@ -43,13 +49,29 @@ public class KeyInfoSymController {
}
/**
* 密钥备份
* 密钥备份(文件下载)
*
* @param backup 参数
*/
@PostMapping("/backup")
public void backupKey(@Valid @RequestBody KeyInfoDTO.Backup backup) {
public ResponseEntity<Resource> backupKey(@Valid @RequestBody KeyInfoDTO.Backup backup) {
backup.setKeyType(KeyCategory.SYM_KEY.getCode());
byte[] content = keyInfoService.backupKey(backup);
String fileName = String.join("-",
"SymKey-Backup",
backup.getStartTime().format(DateFormat.DATE),
backup.getEndTime().format(DateFormat.DATE)
);
// 设置下载响应的 headers
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
// 返回带文件内容的响应
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new ByteArrayResource(content));
}

View File

@ -101,6 +101,10 @@ public abstract class KeyInfoDTO {
@Data
public static class Backup {
/**
* @ignore
*/
private String keyType;
/**
* 开始日期 yyyy-MM-dd
*/

View File

@ -17,6 +17,8 @@ public interface KeyInfoService {
void update(KeyInfoDTO.Update update);
byte[] backupKey(KeyInfoDTO.Backup backup);
void enableKey(List<Long> ids);
void disableKey(List<Long> ids);

View File

@ -52,7 +52,8 @@ public class CryptoServiceServiceImpl implements CryptoServiceService {
public Page<CryptoServiceDTO.View> selectPageList(CryptoServiceDTO.Query query) {
LambdaQueryWrapper<CryptoService> wrapper = new LambdaQueryWrapper<CryptoService>()
.like(StringUtils.hasText(query.getName()), CryptoService::getName, query.getName());
.like(StringUtils.hasText(query.getName()), CryptoService::getName, query.getName())
.orderByDesc(CryptoService::getCreateTime);
IPage<CryptoService> servicePage = cryptoServiceMapper.selectPage(
new Page<>(query.getPageNumber(), query.getPageSize()),

View File

@ -44,7 +44,8 @@ public class DeviceGroupServiceImpl implements DeviceGroupService {
public Page<DeviceGroupDTO.View> selectPageList(DeviceGroupDTO.Query query) {
LambdaQueryWrapper<DeviceGroup> wrapper = new LambdaQueryWrapper<DeviceGroup>()
.like(StringUtils.hasText(query.getName()), DeviceGroup::getName, query.getName());
.like(StringUtils.hasText(query.getName()), DeviceGroup::getName, query.getName())
.orderByDesc(DeviceGroup::getCreateTime);
IPage<DeviceGroup> page = spDeviceGroupMapper.selectPage(
new Page<>(query.getPageNumber(), query.getPageSize()),

View File

@ -41,7 +41,8 @@ public class DeviceServiceImpl implements DeviceService {
LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<Device>()
.eq(StringUtils.hasText(query.getManufacturers()), Device::getManufacturer, query.getManufacturers())
.eq(StringUtils.hasText(query.getModel()), Device::getManufacturerModel, query.getModel())
.like(StringUtils.hasText(query.getName()), Device::getName, query.getName());
.like(StringUtils.hasText(query.getName()), Device::getName, query.getName())
.orderByDesc(Device::getCreateTime);
IPage<Device> page = spDeviceMapper.selectPage(
new Page<>(query.getPageNumber(), query.getPageSize()),

View File

@ -18,6 +18,7 @@ import com.sunyard.chsm.model.entity.KeyTemplate;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.model.EccKey;
import com.sunyard.chsm.service.KeyInfoService;
import com.sunyard.chsm.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.BeanUtils;
@ -28,6 +29,8 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
@ -64,6 +67,7 @@ public class KeyInfoServiceImpl implements KeyInfoService {
new LambdaQueryWrapper<KeyInfo>()
.eq(StringUtils.hasText(query.getKeyType()), KeyInfo::getKeyType, query.getKeyType())
.eq(StringUtils.hasText(query.getStatus()), KeyInfo::getStatus, query.getStatus())
.orderByDesc(KeyInfo::getCreateTime)
);
List<KeyInfo> records = page.getRecords();
if (CollectionUtils.isEmpty(records)) {
@ -188,6 +192,30 @@ public class KeyInfoServiceImpl implements KeyInfoService {
}
@Override
public byte[] backupKey(KeyInfoDTO.Backup backup) {
LocalDate plussed = backup.getStartTime().plusDays(100);
Assert.isTrue(plussed.isAfter(backup.getEndTime()), "备份密钥创建时间范围不能超过100天");
List<KeyInfo> keyInfos = keyInfoMapper.selectList(
new LambdaQueryWrapper<KeyInfo>()
.eq(KeyInfo::getKeyType, backup.getKeyType())
.gt(KeyInfo::getCreateTime, LocalDateTime.of(backup.getStartTime(), LocalTime.MIN))
.lt(KeyInfo::getCreateTime, LocalDateTime.of(backup.getEndTime(), LocalTime.MAX))
);
StringBuilder builder = new StringBuilder();
for (KeyInfo keyInfo : keyInfos) {
List<KeyRecord> records = spKeyRecordMapper.selectList(
new LambdaQueryWrapper<KeyRecord>()
.eq(KeyRecord::getKeyId, keyInfo.getId())
);
keyInfo.setRecords(records);
builder.append(JsonUtils.toJsonString(records)).append(System.lineSeparator());
}
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
private KeyRecord genKeyRecord(KeyInfo info) {
KeyRecord record = new KeyRecord();
record.setId(IdWorker.getId());

View File

@ -43,7 +43,8 @@ public class KeyTemplateServiceImpl implements KeyTemplateService {
@Override
public Page<KeyTemplateDTO.View> selectPageList(KeyTemplateDTO.Query query) {
LambdaQueryWrapper<KeyTemplate> wrapper = new LambdaQueryWrapper<KeyTemplate>()
.eq(StringUtils.hasText(query.getKeyType()), KeyTemplate::getKeyType, query.getKeyType());
.eq(StringUtils.hasText(query.getKeyType()), KeyTemplate::getKeyType, query.getKeyType())
.orderByDesc(KeyTemplate::getCreateTime);
IPage<KeyTemplate> page = keyTemplateMapper.selectPage(
new Page<>(query.getPageNumber(), query.getPageSize()),

View File

@ -9,7 +9,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.sunyard.chsm.utils.DateFormatPattern;
import com.sunyard.chsm.utils.DateFormat;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* @author liulu
@ -55,14 +54,13 @@ public class WebConfig {
public Jackson2ObjectMapperBuilderCustomizer objectMapperBuilderCustomizer() {
return builder -> {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateFormat.TIME));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateFormat.DATE));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateFormat.DATE_TIME));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateFormat.TIME));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateFormat.DATE));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateFormat.DATE_TIME));
builder.modules(javaTimeModule);
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.serializationInclusion(JsonInclude.Include.NON_NULL);