From 4c0a4f2510477ea1362921cffc7da43eab407284 Mon Sep 17 00:00:00 2001 From: xydkj Date: Thu, 30 Apr 2026 16:44:35 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E6=97=A5=E5=BF=97=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 + .../crypto/pcie/model/BackupDataResult.java | 5 + .../pcie/service/JnaPcieCryptoService.java | 94 ++------------ .../controller/NetworkConfigController.java | 1 + .../device/dto/network/BondTableResponse.java | 6 + .../device/service/NetworkConfigService.java | 7 +- .../log/service/AuditBackupService.java | 92 +++++++------ .../log/service/AuditLogRestoreService.java | 122 +++++++++++------- .../log/service/OperationAuditService.java | 10 +- .../log/service/OperationAuditSigner.java | 16 +-- .../db/migration/V1__tms_schema_full.sql | 70 ++++++++++ 11 files changed, 235 insertions(+), 195 deletions(-) diff --git a/pom.xml b/pom.xml index 2127f8c..d85b796 100644 --- a/pom.xml +++ b/pom.xml @@ -108,6 +108,13 @@ gson 2.13.2 + + + + org.apache.commons + commons-csv + 1.10.0 + diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java index c064e61..068f83e 100644 --- a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java @@ -4,6 +4,7 @@ public class BackupDataResult { private byte[] data; private int length; + private byte[] digest; public byte[] getData() { return data; @@ -20,4 +21,8 @@ public class BackupDataResult { public void setLength(int length) { this.length = length; } + + public byte[] getDigest() {return digest;} + + public void setDigest(byte[] digest) {this.digest = digest;} } diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java index b0209a5..13a2706 100644 --- a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java @@ -1,95 +1,14 @@ package com.cisd.tms.integration.crypto.pcie.service; import com.cisd.tms.integration.crypto.config.CryptoCardProperties; -import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds; -import com.cisd.tms.integration.crypto.pcie.PcieCryptoException; -import com.cisd.tms.integration.crypto.pcie.PcieKeyState; -import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate; -import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType; -import com.cisd.tms.integration.crypto.pcie.jna.EccCipher; -import com.cisd.tms.integration.crypto.pcie.jna.EccRefPrivateKey; -import com.cisd.tms.integration.crypto.pcie.jna.EccRefPublicKey; -import com.cisd.tms.integration.crypto.pcie.jna.EccSignature; -import com.cisd.tms.integration.crypto.pcie.jna.EnvelopedKeyBlob; -import com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary; -import com.cisd.tms.integration.crypto.pcie.jna.RsaRefPrivateKey; -import com.cisd.tms.integration.crypto.pcie.jna.RsaRefPublicKey; -import com.cisd.tms.integration.crypto.pcie.jna.SdfDeviceInfo; -import com.cisd.tms.integration.crypto.pcie.jna.SdfFirmwareInfo; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceConf; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceStatus; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeIkComponent; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeKekComponent; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent; -import com.cisd.tms.integration.crypto.pcie.jna.SdfeLoginState; -import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; -import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; -import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest; -import com.cisd.tms.integration.crypto.pcie.model.DeviceConfResult; -import com.cisd.tms.integration.crypto.pcie.model.DeviceCountResult; -import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult; -import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult; -import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccInternalDecryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccInternalEncryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccExternalDecryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccExternalEncryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccExternalSignRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; -import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest; -import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest; -import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; -import com.cisd.tms.integration.crypto.pcie.model.ExportKekComponentRequest; -import com.cisd.tms.integration.crypto.pcie.model.FileCreateRequest; -import com.cisd.tms.integration.crypto.pcie.model.FileReadRequest; -import com.cisd.tms.integration.crypto.pcie.model.FileWriteRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKekRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkRsaRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkRsaRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithKekRequest; -import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyPairRequest; -import com.cisd.tms.integration.crypto.pcie.model.HmacRequest; -import com.cisd.tms.integration.crypto.pcie.model.HmacResult; -import com.cisd.tms.integration.crypto.pcie.model.FirmwareInfoResult; -import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.ImportKekRequest; -import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskEccRequest; -import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskRsaRequest; -import com.cisd.tms.integration.crypto.pcie.model.ImportKeyPairRequest; -import com.cisd.tms.integration.crypto.pcie.model.IkSignRequest; -import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest; -import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest; -import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult; -import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest; -import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest; -import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest; -import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest; -import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPrivateKeyOpRequest; -import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPublicKeyOpRequest; -import com.cisd.tms.integration.crypto.pcie.model.RsaInternalKeyOpRequest; -import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest; -import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest; -import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; -import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeyEncryptRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeySm2SignRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeySm2VerifyRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest; -import com.cisd.tms.integration.crypto.pcie.model.UserKeyVerifyRequest; -import com.sun.jna.Memory; +import com.cisd.tms.integration.crypto.pcie.*; +import com.cisd.tms.integration.crypto.pcie.jna.*; +import com.cisd.tms.integration.crypto.pcie.model.*; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; + import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.function.Supplier; @@ -1687,7 +1606,10 @@ public class JnaPcieCryptoService implements PcieCryptoService { EccInternalSignRequest signRequest = new EccInternalSignRequest(); signRequest.setKeyIndex(keyIndex); signRequest.setData(digest); - return withDefaultPrivateKeyAccess(keyIndex, () -> eccInternalSign(signRequest)); + + BackupDataResult backupDataResult = withDefaultPrivateKeyAccess(keyIndex, () -> eccInternalSign(signRequest)); + backupDataResult.setDigest(digest); + return backupDataResult; } @Override diff --git a/src/main/java/com/cisd/tms/modules/device/controller/NetworkConfigController.java b/src/main/java/com/cisd/tms/modules/device/controller/NetworkConfigController.java index e0d2964..f0fae4c 100644 --- a/src/main/java/com/cisd/tms/modules/device/controller/NetworkConfigController.java +++ b/src/main/java/com/cisd/tms/modules/device/controller/NetworkConfigController.java @@ -29,6 +29,7 @@ public class NetworkConfigController { @Operation(summary = "获取所有网卡名", description = "获取系统中所有网卡名称") @GetMapping("/card/eth-names") + @AuditedOperation(module = ModuleCode.DEVICE, action = ActionType.CREATE, summary = "获取所有网卡名") public ApiResponse> getEthDeviceNames() { return ApiResponse.success(networkConfigService.getEthDeviceNames()); } diff --git a/src/main/java/com/cisd/tms/modules/device/dto/network/BondTableResponse.java b/src/main/java/com/cisd/tms/modules/device/dto/network/BondTableResponse.java index b9c9a6d..1a491f4 100644 --- a/src/main/java/com/cisd/tms/modules/device/dto/network/BondTableResponse.java +++ b/src/main/java/com/cisd/tms/modules/device/dto/network/BondTableResponse.java @@ -3,6 +3,8 @@ package com.cisd.tms.modules.device.dto.network; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data @Schema(description = "Bond分页查询响应数据") public class BondTableResponse { @@ -59,4 +61,8 @@ public class BondTableResponse { allowableValues = {"Active", "Inactive"} ) private String status; + + + @Schema(description = "Bond对应的物理网卡列表", example = "[\"eth0\", \"eth1\"]") + private List slaveList; } \ No newline at end of file diff --git a/src/main/java/com/cisd/tms/modules/device/service/NetworkConfigService.java b/src/main/java/com/cisd/tms/modules/device/service/NetworkConfigService.java index 25f0dc5..a65e83a 100644 --- a/src/main/java/com/cisd/tms/modules/device/service/NetworkConfigService.java +++ b/src/main/java/com/cisd/tms/modules/device/service/NetworkConfigService.java @@ -662,6 +662,7 @@ public class NetworkConfigService { } String bondMode = getBondMode(bondName); + List slaveList = getBondSlaves(bondName); List conLines = executeCommand( "nmcli", @@ -680,12 +681,12 @@ public class NetworkConfigService { boolean hasIp = false; for (String ipWithPrefix : splitAddressList(ipv4Addresses)) { - resultList.add(createBondTableItem(bondName, bondMode, "IPV4", ipWithPrefix, ipv4Gateway, status)); + resultList.add(createBondTableItem(bondName, bondMode, slaveList,"IPV4", ipWithPrefix, ipv4Gateway, status)); hasIp = true; } for (String ipWithPrefix : splitAddressList(ipv6Addresses)) { - resultList.add(createBondTableItem(bondName, bondMode, "IPV6", ipWithPrefix, ipv6Gateway, status)); + resultList.add(createBondTableItem(bondName, bondMode, slaveList,"IPV6", ipWithPrefix, ipv6Gateway, status)); hasIp = true; } @@ -1827,6 +1828,7 @@ public class NetworkConfigService { private BondTableResponse createBondTableItem( String bondName, String bondMode, + List slaveList, String addressType, String ipWithPrefix, String gateway, @@ -1835,6 +1837,7 @@ public class NetworkConfigService { BondTableResponse item = new BondTableResponse(); item.setBondName(bondName); item.setBondMode(bondMode); + item.setSlaveList(slaveList); item.setAddressType(addressType); item.setGateway(gateway == null ? "" : gateway); item.setStatus(status); diff --git a/src/main/java/com/cisd/tms/modules/log/service/AuditBackupService.java b/src/main/java/com/cisd/tms/modules/log/service/AuditBackupService.java index 1c45b7d..2f75b44 100644 --- a/src/main/java/com/cisd/tms/modules/log/service/AuditBackupService.java +++ b/src/main/java/com/cisd/tms/modules/log/service/AuditBackupService.java @@ -14,6 +14,8 @@ import com.cisd.tms.modules.log.repository.BackupRecordRepository; import com.cisd.tms.modules.log.repository.OperationAuditLogRepository; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; @@ -199,9 +201,9 @@ public class AuditBackupService { // 对生成zip文件进行哈希和签名 byte[] zipFileBytes = Files.readAllBytes(zipFile.toPath()); - byte[] zipFileHash = sm3(zipFileBytes); - - byte[] zipFileSign = sign(zipFileHash); + BackupDataResult zipFileBackupData = signWithDigest(zipFileBytes); + byte[] zipFileHash = zipFileBackupData.getDigest(); + byte[] zipFileSign = normalize(zipFileBackupData); record.setFileHash(Base64.getEncoder().encodeToString(zipFileHash)); record.setFileSign(Base64.getEncoder().encodeToString(zipFileSign)); @@ -232,39 +234,37 @@ public class AuditBackupService { ZipOutputStream zos = new ZipOutputStream(fos)) { StringBuilder csvContent = new StringBuilder(); - csvContent.append("日志ID,发生时间,操作角色,认证等级,业务模块,操作动作,操作结果,来源IP,操作摘要,失败原因,审计状态,审计结果,审计人,审计时间,防篡改摘要(SM3),签名值(SM2),创建时间\n"); List logList = operationAuditLogRepository.findAll().orElseGet(ArrayList::new); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - for (OperationAuditLogEntity auditLog : logList) { - String summary = escapeCSV(auditLog.getSummary()); - String errorMsg = escapeCSV(auditLog.getErrorMessage()); - String actionType = auditLog.getActionType() != null ? auditLog.getActionType().name() : ""; - String result = auditLog.getOperationResult() != null ? auditLog.getOperationResult().name() : ""; - - String occurredTime = auditLog.getOccurredAt() != null ? auditLog.getOccurredAt().format(formatter) : ""; - String auditedTime = auditLog.getAuditedAt() != null ? auditLog.getAuditedAt().format(formatter) : ""; - String createdTime = auditLog.getCreateTime() != null ? auditLog.getCreateTime().format(formatter) : ""; - String line = String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", - auditLog.getLogId(), - occurredTime, - auditLog.getOperatorRoleCode() != null ? auditLog.getOperatorRoleCode() : "", - auditLog.getOperatorAuthLevel() != null ? auditLog.getOperatorAuthLevel() : "", - auditLog.getModuleCode(), - actionType, - result, - auditLog.getRemoteIp(), - summary, - errorMsg, - auditLog.getAuditStatus() != null ? auditLog.getAuditStatus() : "", - auditLog.getAuditResult() != null ? auditLog.getAuditResult() : "", - auditLog.getAuditedBy() != null ? auditLog.getAuditedBy() : "", - auditedTime, - auditLog.getPayloadHash(), - auditLog.getSignValue(), - createdTime - ); - csvContent.append(line); + CSVFormat format = CSVFormat.DEFAULT.builder() + .setHeader("日志ID", "发生时间", "操作角色", "认证等级", "业务模块", + "操作动作", "操作结果", "来源IP", "操作摘要", "失败原因", + "审计状态", "审计结果", "审计人", "审计时间", + "防篡改摘要(SM3)", "签名值(SM2)", "创建时间") + .build(); + try (CSVPrinter printer = format.print(csvContent)) { + for (OperationAuditLogEntity auditLog : logList) { + printer.printRecord( + auditLog.getLogId(), + formatDateTime(auditLog.getOccurredAt(), formatter), + nullToEmpty(auditLog.getOperatorRoleCode()), + nullToEmpty(auditLog.getOperatorAuthLevel()), + auditLog.getModuleCode(), + auditLog.getActionType(), + auditLog.getOperationResult(), + auditLog.getRemoteIp(), + auditLog.getSummary(), + auditLog.getErrorMessage(), + nullToEmpty(auditLog.getAuditStatus()), + nullToEmpty(auditLog.getAuditResult()), + nullToEmpty(auditLog.getAuditedBy()), + formatDateTime(auditLog.getAuditedAt(), formatter), + auditLog.getPayloadHash(), + auditLog.getSignValue(), + formatDateTime(auditLog.getCreateTime(), formatter) + ); + } } // 加密 @@ -339,9 +339,9 @@ public class AuditBackupService { // 对生成zip文件进行哈希和签名 byte[] zipFileBytes = Files.readAllBytes(zipFile.toPath()); - byte[] zipFileHash = sm3(zipFileBytes); - - byte[] zipFileSign = sign(zipFileHash); + BackupDataResult zipFileBackupData = signWithDigest(zipFileBytes); + byte[] zipFileHash = zipFileBackupData.getDigest(); + byte[] zipFileSign = normalize(zipFileBackupData); record.setFileHash(Base64.getEncoder().encodeToString(zipFileHash)); record.setFileSign(Base64.getEncoder().encodeToString(zipFileSign)); @@ -378,10 +378,28 @@ public class AuditBackupService { } UserKeySignRequest request = new UserKeySignRequest(); request.setKeyIndex(1); - request.setData(sm3(dataToSign)); + request.setData(dataToSign); return normalize(pcieCryptoService.userKeySignWithSm3(request)); } + private BackupDataResult signWithDigest(byte[] dataToSign){ + if (dataToSign == null) { + throw new IllegalArgumentException("dataToSign is required"); + } + UserKeySignRequest request = new UserKeySignRequest(); + request.setKeyIndex(1); + request.setData(dataToSign); + return pcieCryptoService.userKeySignWithSm3(request); + } + + private String formatDateTime(LocalDateTime dateTime, DateTimeFormatter formatter) { + return dateTime != null ? dateTime.format(formatter) : ""; + } + + private String nullToEmpty(Object obj) { + return obj != null ? obj.toString() : ""; + } + private String escapeCSV(String str) { if (str == null) { return ""; diff --git a/src/main/java/com/cisd/tms/modules/log/service/AuditLogRestoreService.java b/src/main/java/com/cisd/tms/modules/log/service/AuditLogRestoreService.java index 08b0648..2226a71 100644 --- a/src/main/java/com/cisd/tms/modules/log/service/AuditLogRestoreService.java +++ b/src/main/java/com/cisd/tms/modules/log/service/AuditLogRestoreService.java @@ -16,6 +16,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; import org.bouncycastle.crypto.digests.SM3Digest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +32,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.StringReader; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -94,7 +98,7 @@ public class AuditLogRestoreService { // //todo 验签 UserKeyVerifyRequest userKeyVerifyRequest = new UserKeyVerifyRequest(); userKeyVerifyRequest.setKeyIndex(1); - userKeyVerifyRequest.setData(sm3(signatureSource)); + userKeyVerifyRequest.setData(signatureSource); userKeyVerifyRequest.setSignature(signatureBytes); // try { // pcieCryptoService.userKeyVerifyWithSm3(userKeyVerifyRequest); @@ -140,10 +144,9 @@ public class AuditLogRestoreService { List pendingInsertList = new ArrayList<>(); - String[] lines = csvContent.split("\n"); - totalCount = lines.length - 1; - List parsedLogs = parseCsvToEntities(lines); + List parsedLogs = parseCsvToEntities(csvContent); + totalCount = parsedLogs.size(); List incomingSignValues = parsedLogs.stream() .map(OperationAuditLogEntity::getSignValue) .collect(Collectors.toList()); @@ -232,56 +235,77 @@ public class AuditLogRestoreService { outputStream.write(safeData); } - //todo后续改转义 - private List parseCsvToEntities(String[] lines) { + + private List parseCsvToEntities(String csvContent) { List list = new ArrayList<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - for (int i = 1; i < lines.length; i++) { - if (lines[i].trim().isEmpty()) continue; - String[] cols = lines[i].split(",", -1); - OperationAuditLogEntity entity = new OperationAuditLogEntity(); - entity.setLogId(cols[0]); + try (StringReader reader = new StringReader(csvContent); + CSVParser parser = CSVFormat.DEFAULT.builder() + .setHeader() + .setSkipHeaderRecord(true) + .build() + .parse(reader)) { - if (!cols[1].isEmpty()) { - entity.setOccurredAt(LocalDateTime.parse(cols[1], formatter)); + for (CSVRecord record : parser) { + if (record.size() < 17) { + throw new IllegalArgumentException("恢复数据异常"); + } + + OperationAuditLogEntity entity = new OperationAuditLogEntity(); + + entity.setLogId(record.get(0)); + + String occurredAt = record.get(1); + if (!occurredAt.isEmpty()) { + entity.setOccurredAt(LocalDateTime.parse(occurredAt, formatter)); + } + + String roleCode = record.get(2); + if (!roleCode.isEmpty()) entity.setOperatorRoleCode(OperatorRoleCode.valueOf(roleCode)); + + String authLevel = record.get(3); + if (!authLevel.isEmpty()) entity.setOperatorAuthLevel(AuthLevel.valueOf(authLevel)); + + String moduleCode = record.get(4); + if (!moduleCode.isEmpty()) entity.setModuleCode(ModuleCode.valueOf(moduleCode)); + + String actionType = record.get(5); + if (!actionType.isEmpty()) entity.setActionType(ActionType.valueOf(actionType)); + + String operationResult = record.get(6); + if (!operationResult.isEmpty()) entity.setOperationResult(OperationResult.valueOf(operationResult)); + + entity.setRemoteIp(record.get(7)); + + entity.setSummary(record.get(8)); + entity.setErrorMessage(record.get(9)); + + String auditStatus = record.get(10); + if (!auditStatus.isEmpty()) entity.setAuditStatus(AuditStatus.valueOf(auditStatus)); + + String auditResult = record.get(11); + if (!auditResult.isEmpty()) entity.setAuditResult(AuditResult.valueOf(auditResult)); + + entity.setAuditedBy(record.get(12)); + + String auditedAt = record.get(13); + if (!auditedAt.isEmpty()) { + entity.setAuditedAt(LocalDateTime.parse(auditedAt, formatter)); + } + + entity.setPayloadHash(record.get(14)); + entity.setSignValue(record.get(15)); + + String createTime = record.get(16); + if (!createTime.isEmpty()) { + entity.setCreateTime(LocalDateTime.parse(createTime, formatter)); + } + + list.add(entity); } - - if (!cols[2].isEmpty()) entity.setOperatorRoleCode(OperatorRoleCode.valueOf(cols[2])); - - if (!cols[3].isEmpty()) entity.setOperatorAuthLevel(AuthLevel.valueOf(cols[3])); - - if (!cols[4].isEmpty()) entity.setModuleCode(ModuleCode.valueOf(cols[4])); - - if (!cols[5].isEmpty()) entity.setActionType(ActionType.valueOf(cols[5])); - - if (!cols[6].isEmpty()) entity.setOperationResult(OperationResult.valueOf(cols[6])); - - entity.setRemoteIp(cols[7]); - - entity.setSummary(cols[8].replace("\"\"", "\"").replaceAll("^\"|\"$", "")); - - entity.setErrorMessage(cols[9].replace("\"\"", "\"").replaceAll("^\"|\"$", "")); - - if (!cols[10].isEmpty()) entity.setAuditStatus(AuditStatus.valueOf(cols[10])); - - if (!cols[11].isEmpty()) entity.setAuditResult(AuditResult.valueOf(cols[11])); - - entity.setAuditedBy(cols[12]); - - if (!cols[13].isEmpty()) { - entity.setAuditedAt(LocalDateTime.parse(cols[13], formatter)); - } - - entity.setPayloadHash(cols[14]); - - entity.setSignValue(cols[15]); - - if (!cols[16].isEmpty()) { - entity.setCreateTime(LocalDateTime.parse(cols[16], formatter)); - } - - list.add(entity); + } catch (IOException e) { + throw new RuntimeException("CSV 解析失败", e); } return list; } diff --git a/src/main/java/com/cisd/tms/modules/log/service/OperationAuditService.java b/src/main/java/com/cisd/tms/modules/log/service/OperationAuditService.java index f6be513..c491de9 100644 --- a/src/main/java/com/cisd/tms/modules/log/service/OperationAuditService.java +++ b/src/main/java/com/cisd/tms/modules/log/service/OperationAuditService.java @@ -190,17 +190,9 @@ public class OperationAuditService { // // String payload = auditSigner.buildAuditPayload(existLog); // -// //计算SM3哈希 -// DigestRequest request = new DigestRequest(); -// request.setAlgId(Gm0018AlgorithmIds.SM3); -// request.setData(payload.getBytes(StandardCharsets.UTF_8)); -// BackupDataResult payloadHash = pcieCryptoService.digest(request); -// -// -// //todo 验签 // UserKeyVerifyRequest userKeyVerifyRequest = new UserKeyVerifyRequest(); // userKeyVerifyRequest.setKeyIndex(1); -// userKeyVerifyRequest.setData(payloadHash.getData()); +// userKeyVerifyRequest.setData(payload.getBytes(StandardCharsets.UTF_8)); // userKeyVerifyRequest.setSignature(decodeBlob(signValue, "signature is invalid")); // try { // pcieCryptoService.userKeyVerifyWithSm3(userKeyVerifyRequest); diff --git a/src/main/java/com/cisd/tms/modules/log/service/OperationAuditSigner.java b/src/main/java/com/cisd/tms/modules/log/service/OperationAuditSigner.java index 7f09d0f..7c89ccc 100644 --- a/src/main/java/com/cisd/tms/modules/log/service/OperationAuditSigner.java +++ b/src/main/java/com/cisd/tms/modules/log/service/OperationAuditSigner.java @@ -1,8 +1,6 @@ package com.cisd.tms.modules.log.service; -import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds; import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; -import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest; import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService; import com.cisd.tms.modules.log.entity.OperationAuditLogEntity; @@ -37,24 +35,18 @@ public class OperationAuditSigner { } - //todo 生成签名 + //生成签名 public void signEntity(OperationAuditLogEntity entity) { String payload = buildAuditPayload(entity); - //计算SM3哈希 - DigestRequest request = new DigestRequest(); - request.setAlgId(Gm0018AlgorithmIds.SM3); - request.setData(payload.getBytes(StandardCharsets.UTF_8)); - BackupDataResult payloadHash = pcieCryptoService.digest(request); - - entity.setPayloadHash(Base64.getEncoder().encodeToString(payloadHash.getData())); //计算 SM2 签名值 UserKeySignRequest userKeySignRequest = new UserKeySignRequest(); - userKeySignRequest.setData(payloadHash.getData()); + userKeySignRequest.setData(payload.getBytes(StandardCharsets.UTF_8)); userKeySignRequest.setKeyIndex(1); - BackupDataResult sign = pcieCryptoService.userKeySignWithSm3(userKeySignRequest ); + BackupDataResult sign = pcieCryptoService.userKeySignWithSm3(userKeySignRequest); entity.setSignValue(Base64.getEncoder().encodeToString(sign.getData())); + entity.setPayloadHash(Base64.getEncoder().encodeToString(sign.getDigest())); } diff --git a/src/main/resources/db/migration/V1__tms_schema_full.sql b/src/main/resources/db/migration/V1__tms_schema_full.sql index 763e68a..04bac8b 100644 --- a/src/main/resources/db/migration/V1__tms_schema_full.sql +++ b/src/main/resources/db/migration/V1__tms_schema_full.sql @@ -607,3 +607,73 @@ CREATE TABLE IF NOT EXISTS t_trusted_cert ( KEY idx_t_trusted_cert_issuer_dn (issuer_dn(512)), KEY idx_t_trusted_cert_valid_to (valid_to) ); + + +-- ----------------------------------------------------------------------------- +-- 日志表 +-- ----------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS tms_operation_audit_log ( + id BIGINT PRIMARY KEY, + log_id VARCHAR(64) NOT NULL COMMENT '日志唯一标识', + operator_role_code VARCHAR(64) NOT NULL COMMENT '操作角色编码', + operator_auth_level VARCHAR(32) NULL COMMENT '操作时认证等级', + module_code VARCHAR(32) NOT NULL COMMENT '业务模块', + action_type VARCHAR(32) NOT NULL COMMENT '操作动作', + remote_ip VARCHAR(64) NULL COMMENT '来源IP', + operation_result VARCHAR(16) NOT NULL COMMENT '操作结果: SUCCESS/FAILED/DENIED', + summary VARCHAR(512) NOT NULL COMMENT '操作摘要', + error_message VARCHAR(1024) NULL COMMENT '失败原因', + audit_status VARCHAR(16) NOT NULL COMMENT '审计状态: PENDING/REVIEWED', + audit_result VARCHAR(16) NULL COMMENT '审计结果: PASS/REJECT/NEED_VERIFY', + audit_comment VARCHAR(1024) NULL COMMENT '审计意见', + audited_by VARCHAR(64) NULL COMMENT '审计人', + audited_at DATETIME(3) NULL COMMENT '审计时间', + payload_hash VARCHAR(128) NOT NULL COMMENT 'SM3摘要', + sign_value TEXT NOT NULL COMMENT 'SM2签名值', + occurred_at DATETIME(3) NOT NULL COMMENT '操作发生时间', + create_time DATETIME(3) NOT NULL COMMENT '落库时间', + UNIQUE KEY uk_tms_operation_audit_log_log_id (log_id), + KEY idx_tms_operation_audit_log_role_code (operator_role_code), + KEY idx_tms_operation_audit_log_module_code (module_code), + KEY idx_tms_operation_audit_log_action_type (action_type), + KEY idx_tms_operation_audit_log_result (operation_result), + KEY idx_tms_operation_audit_log_audit_status (audit_status), + KEY idx_tms_operation_audit_log_occurred_at (occurred_at) + ); + + + +-- ----------------------------------------------------------------------------- +-- 日志备份记录表 +-- ----------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS tms_log_backup_record ( + id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + record_id VARCHAR(64) NOT NULL COMMENT '备份记录ID', + file_name VARCHAR(255) NOT NULL COMMENT '备份文件名', + backup_type VARCHAR(32) NOT NULL COMMENT '备份类型(如:AUTO/MANUAL)', + file_path VARCHAR(500) NOT NULL COMMENT '文件存储路径', + file_hash VARCHAR(128) NOT NULL COMMENT '文件哈希值', + file_sign VARCHAR(256) DEFAULT NULL COMMENT '文件签名', + backup_result VARCHAR(32) NOT NULL COMMENT '备份结果(SUCCESS/FAILED)', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + sign_data TEXT DEFAULT NULL COMMENT '其他字段签名', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_record_id` (`record_id`), + KEY `idx_create_time` (`create_time`), + KEY `idx_backup_type` (`backup_type`) +) + + + +-- ----------------------------------------------------------------------------- +-- 日志备份配置表 +-- ----------------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS tms_backup_config ( + id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + enable tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用状态 1:启用 0:禁用', + cron_exp varchar(64) DEFAULT NULL COMMENT 'Cron表达式', + retention_count int(11) DEFAULT '1' COMMENT '保留份数', + last_backup_time datetime DEFAULT NULL COMMENT '上次执行时间', + sign_data varchar(255) NOT NULL COMMENT '其他字段的签名值', + PRIMARY KEY (`id`) +) \ No newline at end of file