feat:升级功能、密码卡框架、主密钥接口

This commit is contained in:
waner
2026-03-26 17:30:48 +08:00
parent c1e91e76b0
commit 11ed0b5edf
208 changed files with 16742 additions and 1156 deletions
@@ -1,5 +1,7 @@
package com.cisd.tms.common.config;
import com.cisd.tms.common.config.properties.TmsCorsProperties;
import com.cisd.tms.modules.auth.security.InternalAuthorizationInterceptor;
import com.cisd.tms.security.internal.InternalApiAuthInterceptor;
import com.cisd.tms.security.openapi.OpenApiSignAuthInterceptor;
import com.cisd.tms.common.util.TraceIdUtil;
@@ -12,6 +14,7 @@ import org.slf4j.MDC;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -19,14 +22,20 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class WebMvcConfig implements WebMvcConfigurer {
private final InternalApiAuthInterceptor internalApiAuthInterceptor;
private final InternalAuthorizationInterceptor internalAuthorizationInterceptor;
private final OpenApiSignAuthInterceptor openApiSignAuthInterceptor;
private final TmsCorsProperties corsProperties;
public WebMvcConfig(
InternalApiAuthInterceptor internalApiAuthInterceptor,
OpenApiSignAuthInterceptor openApiSignAuthInterceptor
InternalAuthorizationInterceptor internalAuthorizationInterceptor,
OpenApiSignAuthInterceptor openApiSignAuthInterceptor,
TmsCorsProperties corsProperties
) {
this.internalApiAuthInterceptor = internalApiAuthInterceptor;
this.internalAuthorizationInterceptor = internalAuthorizationInterceptor;
this.openApiSignAuthInterceptor = openApiSignAuthInterceptor;
this.corsProperties = corsProperties;
}
@Bean
@@ -56,10 +65,31 @@ public class WebMvcConfig implements WebMvcConfigurer {
.addPathPatterns("/api/**")
.excludePathPatterns(
"/api/v1/device/status",
"/api/v1/auth/login"
"/api/v1/auth/login",
"/api/v1/auth/password-login",
"/api/v1/auth/ukey-login",
"/api/v1/auth/ukey-login/randoms"
);
registry.addInterceptor(internalAuthorizationInterceptor)
.addPathPatterns("/api/**");
registry.addInterceptor(openApiSignAuthInterceptor)
.addPathPatterns("/openapi/**");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
if (!corsProperties.isEnabled() || corsProperties.getAllowedOriginPatterns().isEmpty()) {
return;
}
registry.addMapping("/**")
.allowedOriginPatterns(corsProperties.getAllowedOriginPatterns().toArray(String[]::new))
.allowedMethods(corsProperties.getAllowedMethods().toArray(String[]::new))
.allowedHeaders(corsProperties.getAllowedHeaders().toArray(String[]::new))
.exposedHeaders(corsProperties.getExposedHeaders().toArray(String[]::new))
.allowCredentials(corsProperties.isAllowCredentials())
.maxAge(corsProperties.getMaxAgeSeconds());
}
}
@@ -0,0 +1,94 @@
package com.cisd.tms.common.config.properties;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "tms.web.cors")
public class TmsCorsProperties {
private boolean enabled = true;
private List<String> allowedOriginPatterns = new ArrayList<>(List.of(
"http://localhost:*",
"http://127.0.0.1:*"
));
private List<String> allowedMethods = new ArrayList<>(List.of(
"GET",
"POST",
"PUT",
"DELETE",
"OPTIONS"
));
private List<String> allowedHeaders = new ArrayList<>(List.of(
"Authorization",
"Content-Type",
"X-Requested-With",
"X-Internal-Token",
"X-App-Id",
"X-Timestamp",
"X-Nonce",
"X-Signature",
"X-Trace-Id"
));
private List<String> exposedHeaders = new ArrayList<>(List.of(
"X-Trace-Id"
));
private boolean allowCredentials = true;
private long maxAgeSeconds = 3600;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<String> getAllowedOriginPatterns() {
return allowedOriginPatterns;
}
public void setAllowedOriginPatterns(List<String> allowedOriginPatterns) {
this.allowedOriginPatterns = allowedOriginPatterns;
}
public List<String> getAllowedMethods() {
return allowedMethods;
}
public void setAllowedMethods(List<String> allowedMethods) {
this.allowedMethods = allowedMethods;
}
public List<String> getAllowedHeaders() {
return allowedHeaders;
}
public void setAllowedHeaders(List<String> allowedHeaders) {
this.allowedHeaders = allowedHeaders;
}
public List<String> getExposedHeaders() {
return exposedHeaders;
}
public void setExposedHeaders(List<String> exposedHeaders) {
this.exposedHeaders = exposedHeaders;
}
public boolean isAllowCredentials() {
return allowCredentials;
}
public void setAllowCredentials(boolean allowCredentials) {
this.allowCredentials = allowCredentials;
}
public long getMaxAgeSeconds() {
return maxAgeSeconds;
}
public void setMaxAgeSeconds(long maxAgeSeconds) {
this.maxAgeSeconds = maxAgeSeconds;
}
}
@@ -8,6 +8,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
public class TmsSecurityProperties {
private String internalToken = "change-me-internal-token";
private final InternalAuth internalAuth = new InternalAuth();
private final Openapi openapi = new Openapi();
public String getInternalToken() {
@@ -18,10 +19,53 @@ public class TmsSecurityProperties {
this.internalToken = internalToken;
}
public InternalAuth getInternalAuth() {
return internalAuth;
}
public Openapi getOpenapi() {
return openapi;
}
public static class InternalAuth {
private boolean enabled = true;
private String debugRoleCode = "KEY_ADMIN";
private String debugAuthLevel = "FULL";
private String debugSessionToken = "DEBUG-BYPASS";
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getDebugRoleCode() {
return debugRoleCode;
}
public void setDebugRoleCode(String debugRoleCode) {
this.debugRoleCode = debugRoleCode;
}
public String getDebugAuthLevel() {
return debugAuthLevel;
}
public void setDebugAuthLevel(String debugAuthLevel) {
this.debugAuthLevel = debugAuthLevel;
}
public String getDebugSessionToken() {
return debugSessionToken;
}
public void setDebugSessionToken(String debugSessionToken) {
this.debugSessionToken = debugSessionToken;
}
}
public static class Openapi {
private long timestampSkewSeconds = 300;
private Map<String, String> clients = new HashMap<>();
@@ -7,6 +7,7 @@ import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import jakarta.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
@@ -33,6 +34,7 @@ public class PcieSessionTemplate {
private final Object lock = new Object();
private volatile PcieNativeLibrary nativeLibrary;
private volatile Pointer sharedDeviceHandle;
public PcieSessionTemplate(CryptoCardProperties properties, PcieErrorMapper errorMapper) {
this.properties = properties;
@@ -42,32 +44,22 @@ public class PcieSessionTemplate {
public <T> T withDevice(String apiName, DeviceCallback<T> callback) {
synchronized (lock) {
PcieNativeLibrary lib = ensureLibraryLoaded();
PointerByReference deviceRef = new PointerByReference();
int openRc = lib.SDF_OpenDevice(deviceRef);
ensureSuccess(apiName + ":SDF_OpenDevice", openRc);
Pointer device = deviceRef.getValue();
try {
return callback.apply(lib, device);
} finally {
int closeRc = lib.SDF_CloseDevice(device);
if (closeRc != 0) {
log.warn("{} close device failed: {}", apiName, errorMapper.toMessage(closeRc));
}
}
Pointer device = ensureSharedDeviceOpened(apiName, lib);
return callback.apply(lib, device);
}
}
public <T> T withSession(String apiName, SessionCallback<T> callback) {
return withDevice(apiName, (lib, deviceHandle) -> {
PointerByReference sessionRef = new PointerByReference();
Pointer ph = new Memory(8L);
sessionRef.setValue(ph);
int openSessionRc = lib.SDF_OpenSession(deviceHandle, sessionRef);
ensureSuccess(apiName + ":SDF_OpenSession", openSessionRc);
synchronized (lock) {
PcieNativeLibrary lib = ensureLibraryLoaded();
Pointer deviceHandle = ensureSharedDeviceOpened(apiName, lib);
Pointer session = tryOpenSession(apiName, lib, deviceHandle);
if (session == null) {
resetSharedDevice(lib);
deviceHandle = ensureSharedDeviceOpened(apiName, lib);
session = openSessionOrThrow(apiName, lib, deviceHandle);
}
Pointer session = sessionRef.getValue();
try {
return callback.apply(lib, deviceHandle, session);
} finally {
@@ -76,7 +68,7 @@ public class PcieSessionTemplate {
log.warn("{} close session failed: {}", apiName, errorMapper.toMessage(closeSessionRc));
}
}
});
}
}
public void ensureSuccess(String apiName, int retCode) {
@@ -85,6 +77,13 @@ public class PcieSessionTemplate {
}
}
@PreDestroy
void closeSharedDevice() {
synchronized (lock) {
closeSharedDevice(libOrNull());
}
}
private PcieNativeLibrary ensureLibraryLoaded() {
PcieNativeLibrary cached = nativeLibrary;
if (cached != null) {
@@ -116,4 +115,55 @@ public class PcieSessionTemplate {
return nativeLibrary;
}
}
private Pointer ensureSharedDeviceOpened(String apiName, PcieNativeLibrary lib) {
Pointer cached = sharedDeviceHandle;
if (cached != null) {
return cached;
}
PointerByReference deviceRef = new PointerByReference();
int openRc = lib.SDF_OpenDevice(deviceRef);
ensureSuccess(apiName + ":SDF_OpenDevice", openRc);
sharedDeviceHandle = deviceRef.getValue();
return sharedDeviceHandle;
}
private Pointer tryOpenSession(String apiName, PcieNativeLibrary lib, Pointer deviceHandle) {
PointerByReference sessionRef = new PointerByReference();
int openSessionRc = lib.SDF_OpenSession(deviceHandle, sessionRef);
if (openSessionRc == 0) {
return sessionRef.getValue();
}
log.warn("{} open session failed, will reset shared device and retry once: {}", apiName, errorMapper.toMessage(openSessionRc));
return null;
}
private Pointer openSessionOrThrow(String apiName, PcieNativeLibrary lib, Pointer deviceHandle) {
PointerByReference sessionRef = new PointerByReference();
int openSessionRc = lib.SDF_OpenSession(deviceHandle, sessionRef);
ensureSuccess(apiName + ":SDF_OpenSession", openSessionRc);
return sessionRef.getValue();
}
private void resetSharedDevice(PcieNativeLibrary lib) {
closeSharedDevice(lib);
}
private void closeSharedDevice(PcieNativeLibrary lib) {
Pointer device = sharedDeviceHandle;
if (device == null || lib == null) {
return;
}
sharedDeviceHandle = null;
int closeRc = lib.SDF_CloseDevice(device);
if (closeRc != 0) {
log.warn("close shared device failed: {}", errorMapper.toMessage(closeRc));
}
}
private PcieNativeLibrary libOrNull() {
return nativeLibrary;
}
}
@@ -154,7 +154,7 @@ public interface PcieNativeLibrary extends Library {
int SDFE_InitIdentify(Pointer hSessionHandle, byte[] oldPin, int oldPinLen, byte[] newPin, int newPinLen);
int SDFE_DeviceStatusGet(Pointer hSessionHandle, Pointer pDeviceStatus);
int SDFE_DeviceStatusGet(Pointer hSessionHandle, SdfeDeviceStatus deviceStatus);
int SDFE_DeviceSelfTest(Pointer hSessionHandle);
@@ -245,15 +245,15 @@ public interface PcieNativeLibrary extends Library {
int SDFE_UnlockUkey(Pointer hSessionHandle, byte[] adminPin, int adminPinLen, byte[] userPin, int userPinLen);
int SDFE_ReadLMKComponent(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen);
int SDFE_ReadUkeyLMKComponent(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen);
int SDFE_ReadUkeyIKComponent(Pointer hSessionHandle, int keyType, byte[] ukeyPin, int ukeyPinLen);
int SDFE_GenerateCertificate(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen);
int SDFE_GenerateUkeyCertificate(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen);
int SDFE_LoginoutAdmin(Pointer hSessionHandle, byte adminIndex);
int SDFE_LoginoutUkey(Pointer hSessionHandle, byte adminIndex);
int SDFE_LoginStatus(Pointer hSessionHandle, SdfeLoginState loginState);
int SDFE_UkeyLoginStatus(Pointer hSessionHandle, SdfeLoginState loginState);
int SDFE_HmacInit(Pointer hSessionHandle, int algId, byte[] key, int keyLen);
@@ -3,6 +3,7 @@ package com.cisd.tms.integration.crypto.pcie.jna;
import com.sun.jna.Structure;
@Structure.FieldOrder({
"type",
"level",
"devCount",
"rsaKeyCount",
@@ -13,6 +14,7 @@ import com.sun.jna.Structure;
})
public class SdfeDeviceConf extends Structure {
public int type;
public int level;
public int devCount;
public int rsaKeyCount;
@@ -0,0 +1,51 @@
package com.cisd.tms.integration.crypto.pcie.jna;
import com.sun.jna.Structure;
@Structure.FieldOrder({
"fsmState",
"dkeyState",
"errorCode",
"version",
"commit",
"frequency",
"pcieSpeed",
"pcieWidth",
"chipTemp",
"chipVoltage",
"boardTemp",
"boardVoltage",
"boardCurrent",
"chipTempmin",
"chipTempmax",
"boardVolmin",
"boardVolmax",
"fsTotalKb",
"fsFreeKb"
})
public class SdfeDeviceStatus extends Structure {
public int fsmState;
public int dkeyState;
public int errorCode;
public int version;
public int commit;
public int frequency;
public int pcieSpeed;
public int pcieWidth;
public float chipTemp;
public float chipVoltage;
public float boardTemp;
public float boardVoltage;
public float boardCurrent;
public float chipTempmin;
public float chipTempmax;
public float boardVolmin;
public float boardVolmax;
public int fsTotalKb;
public int fsFreeKb;
public SdfeDeviceStatus() {
super(ALIGN_NONE);
}
}
@@ -2,6 +2,7 @@ package com.cisd.tms.integration.crypto.pcie.model;
public class DeviceConfResult {
private int type;
private int level;
private int devCount;
private int rsaKeyCount;
@@ -10,6 +11,14 @@ public class DeviceConfResult {
private int sessKeyCount;
private int fileSysCapacity;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getLevel() {
return level;
}
@@ -12,6 +12,13 @@ public class DeviceInfoResult {
private int symAlgAbility;
private int hashAlgAbility;
private int bufferSize;
private String deviceVersionText;
private String standardVersionText;
private String asymmetricAlgorithmsText;
private String asymmetricKeyBitsText;
private String symmetricAlgorithmsText;
private String hashAlgorithmsText;
private String bufferSizeText;
public String getIssuerName() {
return issuerName;
@@ -92,4 +99,60 @@ public class DeviceInfoResult {
public void setBufferSize(int bufferSize) {
this.bufferSize = bufferSize;
}
public String getDeviceVersionText() {
return deviceVersionText;
}
public void setDeviceVersionText(String deviceVersionText) {
this.deviceVersionText = deviceVersionText;
}
public String getStandardVersionText() {
return standardVersionText;
}
public void setStandardVersionText(String standardVersionText) {
this.standardVersionText = standardVersionText;
}
public String getAsymmetricAlgorithmsText() {
return asymmetricAlgorithmsText;
}
public void setAsymmetricAlgorithmsText(String asymmetricAlgorithmsText) {
this.asymmetricAlgorithmsText = asymmetricAlgorithmsText;
}
public String getAsymmetricKeyBitsText() {
return asymmetricKeyBitsText;
}
public void setAsymmetricKeyBitsText(String asymmetricKeyBitsText) {
this.asymmetricKeyBitsText = asymmetricKeyBitsText;
}
public String getSymmetricAlgorithmsText() {
return symmetricAlgorithmsText;
}
public void setSymmetricAlgorithmsText(String symmetricAlgorithmsText) {
this.symmetricAlgorithmsText = symmetricAlgorithmsText;
}
public String getHashAlgorithmsText() {
return hashAlgorithmsText;
}
public void setHashAlgorithmsText(String hashAlgorithmsText) {
this.hashAlgorithmsText = hashAlgorithmsText;
}
public String getBufferSizeText() {
return bufferSizeText;
}
public void setBufferSizeText(String bufferSizeText) {
this.bufferSizeText = bufferSizeText;
}
}
@@ -1,9 +1,30 @@
package com.cisd.tms.integration.crypto.pcie.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class DeviceStatusResult {
@JsonIgnore
private byte[] statusData;
private int length;
private String statusHex;
private int fsmState;
private String fsmStateText;
private int commit;
private String commitHex;
private int frequencyMhz;
private String frequencyText;
private int pcieSpeed;
private int pcieWidth;
private String pcieInfoText;
private double boardTempC;
private String boardTempText;
private double boardVoltageV;
private String boardVoltageText;
private int fsTotalKb;
private String fsTotalText;
private int fsFreeKb;
private String fsFreeText;
public byte[] getStatusData() {
return statusData;
@@ -20,4 +41,148 @@ public class DeviceStatusResult {
public void setLength(int length) {
this.length = length;
}
public String getStatusHex() {
return statusHex;
}
public void setStatusHex(String statusHex) {
this.statusHex = statusHex;
}
public int getFsmState() {
return fsmState;
}
public void setFsmState(int fsmState) {
this.fsmState = fsmState;
}
public String getFsmStateText() {
return fsmStateText;
}
public void setFsmStateText(String fsmStateText) {
this.fsmStateText = fsmStateText;
}
public int getCommit() {
return commit;
}
public void setCommit(int commit) {
this.commit = commit;
}
public String getCommitHex() {
return commitHex;
}
public void setCommitHex(String commitHex) {
this.commitHex = commitHex;
}
public int getFrequencyMhz() {
return frequencyMhz;
}
public void setFrequencyMhz(int frequencyMhz) {
this.frequencyMhz = frequencyMhz;
}
public String getFrequencyText() {
return frequencyText;
}
public void setFrequencyText(String frequencyText) {
this.frequencyText = frequencyText;
}
public int getPcieSpeed() {
return pcieSpeed;
}
public void setPcieSpeed(int pcieSpeed) {
this.pcieSpeed = pcieSpeed;
}
public int getPcieWidth() {
return pcieWidth;
}
public void setPcieWidth(int pcieWidth) {
this.pcieWidth = pcieWidth;
}
public String getPcieInfoText() {
return pcieInfoText;
}
public void setPcieInfoText(String pcieInfoText) {
this.pcieInfoText = pcieInfoText;
}
public double getBoardTempC() {
return boardTempC;
}
public void setBoardTempC(double boardTempC) {
this.boardTempC = boardTempC;
}
public String getBoardTempText() {
return boardTempText;
}
public void setBoardTempText(String boardTempText) {
this.boardTempText = boardTempText;
}
public double getBoardVoltageV() {
return boardVoltageV;
}
public void setBoardVoltageV(double boardVoltageV) {
this.boardVoltageV = boardVoltageV;
}
public String getBoardVoltageText() {
return boardVoltageText;
}
public void setBoardVoltageText(String boardVoltageText) {
this.boardVoltageText = boardVoltageText;
}
public int getFsTotalKb() {
return fsTotalKb;
}
public void setFsTotalKb(int fsTotalKb) {
this.fsTotalKb = fsTotalKb;
}
public String getFsTotalText() {
return fsTotalText;
}
public void setFsTotalText(String fsTotalText) {
this.fsTotalText = fsTotalText;
}
public int getFsFreeKb() {
return fsFreeKb;
}
public void setFsFreeKb(int fsFreeKb) {
this.fsFreeKb = fsFreeKb;
}
public String getFsFreeText() {
return fsFreeText;
}
public void setFsFreeText(String fsFreeText) {
this.fsFreeText = fsFreeText;
}
}
@@ -16,6 +16,7 @@ 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.SdfeDeviceConf;
import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceStatus;
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;
@@ -129,6 +130,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
conf.read();
DeviceConfResult result = new DeviceConfResult();
result.setType(conf.type);
result.setLevel(conf.level);
result.setDevCount(conf.devCount);
result.setRsaKeyCount(conf.rsaKeyCount);
@@ -158,6 +160,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
result.setSymAlgAbility(info.symAlgAbility);
result.setHashAlgAbility(info.hashAlgAbility);
result.setBufferSize(info.bufferSize);
PcieDeviceInfoFormatter.enrich(result);
return result;
});
}
@@ -192,6 +195,40 @@ public class JnaPcieCryptoService implements PcieCryptoService {
}
}
@Override
public byte[] initializeMasterKey(byte[] oldPin, byte[] newPin) {
byte[] oldPinValue = requireNonEmptyBytes("oldPin", oldPin);
byte[] newPinValue = requireNonEmptyBytes("newPin", newPin);
try {
return sessionTemplate.withSession("SDFE_InitializeMasterKey", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess(
"SDFE_InitIdentify",
lib.SDFE_InitIdentify(sessionHandle, oldPinValue, oldPinValue.length, newPinValue, newPinValue.length)
);
sessionTemplate.ensureSuccess("SDFE_GenerateLMK", lib.SDFE_GenerateLMK(sessionHandle));
sessionTemplate.ensureSuccess("SDFE_LoadLMK", lib.SDFE_LoadLMK(sessionHandle));
sessionTemplate.ensureSuccess("SDFE_GenerateIK", lib.SDFE_GenerateIK(sessionHandle, IK_KEY_TYPE_DEVICE));
sessionTemplate.ensureSuccess("SDFE_GenerateIK", lib.SDFE_GenerateIK(sessionHandle, IK_KEY_TYPE_AUTH));
int retCode = lib.SDFE_CheckLMK(sessionHandle);
if (retCode != 0) {
if ((retCode & 0xFF) == SDFE_INIT_STATUS_LOW_BYTE) {
throw new IllegalStateException("master key initialization failed");
}
sessionTemplate.ensureSuccess("SDFE_CheckLMK", retCode);
}
byte[] mac = new byte[LMK_SEED_MAC_LENGTH];
sessionTemplate.ensureSuccess("SDFE_ExportLMKSeedMAC", lib.SDFE_ExportLMKSeedMAC(sessionHandle, mac));
return Arrays.copyOf(mac, mac.length);
});
} finally {
wipe(oldPinValue);
wipe(newPinValue);
}
}
@Override
public void deviceSelfTest() {
sessionTemplate.withSession("SDFE_DeviceSelfTest", (lib, deviceHandle, sessionHandle) -> {
@@ -202,15 +239,16 @@ public class JnaPcieCryptoService implements PcieCryptoService {
@Override
public DeviceStatusResult getDeviceStatus() {
int size = 8;
return sessionTemplate.withSession("SDFE_DeviceStatusGet", (lib, deviceHandle, sessionHandle) -> {
Memory statusMemory = new Memory(8);
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, statusMemory));
SdfeDeviceStatus status = new SdfeDeviceStatus();
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, status));
status.read();
int size = status.size();
DeviceStatusResult result = new DeviceStatusResult();
// result.setLength(size);
result.setStatusData(statusMemory.getByteArray(0, size));
result.setLength(size);
result.setStatusData(status.getPointer().getByteArray(0, size));
PcieDeviceStatusFormatter.enrich(result, status);
return result;
});
}
@@ -1611,15 +1649,9 @@ public class JnaPcieCryptoService implements PcieCryptoService {
}
@Override
public BackupDataResult backupLmkEx(int outBufferSize) {
int size = requirePositive("outBufferSize", outBufferSize);
public BackupDataResult backupLmkEx() {
return sessionTemplate.withSession("SDFE_BackupLMK_EX", (lib, deviceHandle, sessionHandle) -> {
SdfeLmkComponent output = new SdfeLmkComponent();
int structSize = output.size();
if (size < structSize) {
throw new IllegalArgumentException("outBufferSize must be >= " + structSize);
}
sessionTemplate.ensureSuccess("SDFE_BackupLMK_EX", lib.SDFE_BackupLMK_EX(sessionHandle, output));
byte[] outputBytes = toBytes(output);
return toBackupResult("SDFE_BackupLMK_EX", outputBytes, outputBytes.length);
@@ -1781,8 +1813,11 @@ public class JnaPcieCryptoService implements PcieCryptoService {
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
try {
sessionTemplate.withSession("SDFE_ReadLMKComponent", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess("SDFE_ReadLMKComponent", lib.SDFE_ReadLMKComponent(sessionHandle, pin, pin.length));
sessionTemplate.withSession("SDFE_ReadUkeyLMKComponent", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess(
"SDFE_ReadUkeyLMKComponent",
lib.SDFE_ReadUkeyLMKComponent(sessionHandle, pin, pin.length)
);
return null;
});
} finally {
@@ -1813,8 +1848,11 @@ public class JnaPcieCryptoService implements PcieCryptoService {
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
try {
sessionTemplate.withSession("SDFE_GenerateCertificate", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess("SDFE_GenerateCertificate", lib.SDFE_GenerateCertificate(sessionHandle, pin, pin.length));
sessionTemplate.withSession("SDFE_GenerateUkeyCertificate", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess(
"SDFE_GenerateUkeyCertificate",
lib.SDFE_GenerateUkeyCertificate(sessionHandle, pin, pin.length)
);
return null;
});
} finally {
@@ -1826,17 +1864,17 @@ public class JnaPcieCryptoService implements PcieCryptoService {
public void logoutAdmin(int adminIndex) {
int safeAdminIndex = requireByteRange("adminIndex", adminIndex);
sessionTemplate.withSession("SDFE_LoginoutAdmin", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess("SDFE_LoginoutAdmin", lib.SDFE_LoginoutAdmin(sessionHandle, (byte) safeAdminIndex));
sessionTemplate.withSession("SDFE_LoginoutUkey", (lib, deviceHandle, sessionHandle) -> {
sessionTemplate.ensureSuccess("SDFE_LoginoutUkey", lib.SDFE_LoginoutUkey(sessionHandle, (byte) safeAdminIndex));
return null;
});
}
@Override
public LoginStatusResult loginStatus() {
return sessionTemplate.withSession("SDFE_LoginStatus", (lib, deviceHandle, sessionHandle) -> {
return sessionTemplate.withSession("SDFE_UkeyLoginStatus", (lib, deviceHandle, sessionHandle) -> {
SdfeLoginState state = new SdfeLoginState();
sessionTemplate.ensureSuccess("SDFE_LoginStatus", lib.SDFE_LoginStatus(sessionHandle, state));
sessionTemplate.ensureSuccess("SDFE_UkeyLoginStatus", lib.SDFE_UkeyLoginStatus(sessionHandle, state));
state.read();
LoginStatusResult result = new LoginStatusResult();
@@ -2,6 +2,7 @@ package com.cisd.tms.integration.crypto.pcie.service;
import com.cisd.tms.integration.crypto.pcie.PcieKeyState;
import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType;
import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceStatus;
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;
@@ -100,6 +101,19 @@ public class MockPcieCryptoService implements PcieCryptoService {
requireNonEmptyBytes("newPin", newPin);
}
@Override
public byte[] initializeMasterKey(byte[] oldPin, byte[] newPin) {
initIdentify(oldPin, newPin);
generateLmk();
loadLmk();
generateIk(1);
generateIk(2);
if (!checkLmk()) {
throw new IllegalStateException("master key initialization failed");
}
return exportLmkSeedMac();
}
@Override
public void deviceSelfTest() {
// no-op
@@ -107,7 +121,7 @@ public class MockPcieCryptoService implements PcieCryptoService {
@Override
public DeviceStatusResult getDeviceStatus() {
int size = 8;
int size = new SdfeDeviceStatus().size();
DeviceStatusResult result = new DeviceStatusResult();
result.setLength(size);
result.setStatusData(new byte[size]);
@@ -679,9 +693,8 @@ public class MockPcieCryptoService implements PcieCryptoService {
}
@Override
public BackupDataResult backupLmkEx(int outBufferSize) {
int size = requirePositive("outBufferSize", outBufferSize);
return mockBackup(size, 0x11);
public BackupDataResult backupLmkEx() {
return mockBackup(new com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent().size(), 0x11);
}
@Override
@@ -71,6 +71,8 @@ public interface PcieCryptoService {
void initIdentify(byte[] oldPin, byte[] newPin);
byte[] initializeMasterKey(byte[] oldPin, byte[] newPin);
void deviceSelfTest();
DeviceStatusResult getDeviceStatus();
@@ -209,7 +211,7 @@ public interface PcieCryptoService {
byte[] exportLmkSeedMac();
BackupDataResult backupLmkEx(int outBufferSize);
BackupDataResult backupLmkEx();
void recoverLmkEx(byte[] lmkComponent);
@@ -0,0 +1,146 @@
package com.cisd.tms.integration.crypto.pcie.service;
import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
final class PcieDeviceInfoFormatter {
private static final int ASYM_RSA = 0x00010000;
private static final int ASYM_SM2_SIGN = 0x00020200;
private static final int ASYM_SM2_DH = 0x00020400;
private static final int ASYM_SM2_ENC = 0x00020800;
private static final int SYM_SM1 = 0x00000100;
private static final int SYM_SM4 = 0x00000400;
private static final int SYM_AES128 = 0x00008000;
private static final int SYM_AES192 = 0x00010000;
private static final int SYM_AES256 = 0x00020000;
private static final int HASH_SM3 = 0x00000001;
private static final int HASH_SHA256 = 0x00000004;
private static final int ASYM_BITS_256 = 0x00000100;
private static final int ASYM_BITS_2048 = 0x08000000;
private PcieDeviceInfoFormatter() {
}
static void enrich(DeviceInfoResult result) {
if (result == null) {
return;
}
result.setDeviceVersionText(formatDeviceVersion(result.getDeviceVersion()));
result.setStandardVersionText(formatStandardVersion(result.getStandardVersion()));
result.setAsymmetricAlgorithmsText(joinNonEmpty(decodeAsymmetricAlgorithms(result.getAsymAlgAbility0())));
result.setAsymmetricKeyBitsText(joinNonEmpty(decodeAsymmetricKeyBits(result.getAsymAlgAbility1())));
result.setSymmetricAlgorithmsText(joinNonEmpty(decodeSymmetricAlgorithms(result.getSymAlgAbility())));
result.setHashAlgorithmsText(joinNonEmpty(decodeHashAlgorithms(result.getHashAlgAbility())));
result.setBufferSizeText(formatBufferSize(result.getBufferSize()));
}
private static String formatDeviceVersion(int rawValue) {
byte[] bytes = ByteBuffer.allocate(Integer.BYTES)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt(rawValue)
.array();
String decoded = new String(bytes, StandardCharsets.US_ASCII)
.replace("\u0000", "")
.trim();
if (!decoded.isEmpty() && decoded.chars().allMatch(PcieDeviceInfoFormatter::isPrintableVersionChar)) {
return decoded.startsWith("V") ? decoded : "V" + decoded;
}
return "0x" + Integer.toHexString(rawValue);
}
private static boolean isPrintableVersionChar(int value) {
return (value >= '0' && value <= '9') || value == '.' || value == 'V' || value == 'v';
}
private static String formatStandardVersion(int rawValue) {
int standard = (rawValue >>> 16) & 0xFFFF;
int yearHi = (rawValue >>> 8) & 0xFF;
int yearLo = rawValue & 0xFF;
if (standard > 0 && yearHi > 0 && yearLo > 0) {
return String.format("GMT %04x-%02x%02x", standard, yearHi, yearLo).toUpperCase();
}
return "0x" + Integer.toHexString(rawValue);
}
private static List<String> decodeAsymmetricAlgorithms(int rawValue) {
List<String> values = new ArrayList<>();
if ((rawValue & ASYM_SM2_SIGN) == ASYM_SM2_SIGN) {
values.add("SM2_SIGN");
}
if ((rawValue & ASYM_SM2_DH) == ASYM_SM2_DH) {
values.add("SM2_DH");
}
if ((rawValue & ASYM_SM2_ENC) == ASYM_SM2_ENC) {
values.add("SM2_ENC");
}
if ((rawValue & ASYM_RSA) == ASYM_RSA) {
values.add("RSA");
}
return values;
}
private static List<String> decodeAsymmetricKeyBits(int rawValue) {
List<String> values = new ArrayList<>();
if ((rawValue & ASYM_BITS_256) == ASYM_BITS_256) {
values.add("256");
}
if ((rawValue & ASYM_BITS_2048) == ASYM_BITS_2048) {
values.add("2048");
}
if (!values.isEmpty()) {
values.add("bits");
}
return values;
}
private static List<String> decodeSymmetricAlgorithms(int rawValue) {
List<String> values = new ArrayList<>();
if ((rawValue & SYM_SM1) == SYM_SM1) {
values.add("SM1");
}
if ((rawValue & SYM_SM4) == SYM_SM4) {
values.add("SM4");
}
if ((rawValue & SYM_AES128) == SYM_AES128) {
values.add("AES128");
}
if ((rawValue & SYM_AES192) == SYM_AES192) {
values.add("AES192");
}
if ((rawValue & SYM_AES256) == SYM_AES256) {
values.add("AES256");
}
return values;
}
private static List<String> decodeHashAlgorithms(int rawValue) {
List<String> values = new ArrayList<>();
if ((rawValue & HASH_SM3) == HASH_SM3) {
values.add("SM3");
}
if ((rawValue & HASH_SHA256) == HASH_SHA256) {
values.add("SHA256");
}
return values;
}
private static String formatBufferSize(int rawValue) {
if (rawValue > 0 && rawValue % 1024 == 0) {
return (rawValue / 1024) + " KB";
}
return rawValue + " B";
}
private static String joinNonEmpty(List<String> values) {
return String.join(" ", values);
}
}
@@ -0,0 +1,81 @@
package com.cisd.tms.integration.crypto.pcie.service;
import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceStatus;
import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.Locale;
public final class PcieDeviceStatusFormatter {
private PcieDeviceStatusFormatter() {
}
static void enrich(DeviceStatusResult result, SdfeDeviceStatus status) {
if (result == null || status == null) {
return;
}
byte[] normalized = normalize(result.getStatusData(), result.getLength());
result.setLength(normalized.length);
result.setStatusHex(HexFormat.of().formatHex(normalized));
result.setFsmState(status.fsmState);
result.setFsmStateText(formatFsmState(status.fsmState));
result.setCommit(status.commit);
result.setCommitHex(String.format(Locale.ROOT, "0x%08x", status.commit));
result.setFrequencyMhz(status.frequency);
result.setFrequencyText(status.frequency + "M");
result.setPcieSpeed(status.pcieSpeed);
result.setPcieWidth(status.pcieWidth);
result.setPcieInfoText(formatPcieInfo(status.pcieSpeed, status.pcieWidth));
result.setBoardTempC(round(status.boardTemp));
result.setBoardTempText(formatFloat(status.boardTemp, "°C"));
result.setBoardVoltageV(round(status.boardVoltage));
result.setBoardVoltageText(formatFloat(status.boardVoltage, "V"));
result.setFsTotalKb(status.fsTotalKb);
result.setFsTotalText(status.fsTotalKb + " KB");
result.setFsFreeKb(status.fsFreeKb);
result.setFsFreeText(status.fsFreeKb + " KB");
}
public static void ensureHex(DeviceStatusResult result) {
if (result == null) {
return;
}
if (result.getStatusHex() == null || result.getStatusHex().isBlank()) {
byte[] normalized = normalize(result.getStatusData(), result.getLength());
result.setLength(normalized.length);
result.setStatusHex(HexFormat.of().formatHex(normalized));
}
}
private static String formatFsmState(int fsmState) {
return switch (fsmState) {
case 0 -> "就绪状态";
case 1 -> "未初始化状态";
default -> "状态码:" + fsmState;
};
}
private static String formatPcieInfo(int speed, int width) {
if (speed <= 0 || width <= 0) {
return "";
}
return "GEN" + speed + " X" + width;
}
private static double round(float value) {
return Math.round(value * 100.0d) / 100.0d;
}
private static String formatFloat(float value, String unit) {
return String.format(Locale.ROOT, "%.2f %s", round(value), unit);
}
private static byte[] normalize(byte[] data, int length) {
if (data == null || data.length == 0) {
return new byte[0];
}
int safeLength = length > 0 && length <= data.length ? length : data.length;
return Arrays.copyOf(data, safeLength);
}
}
@@ -1,18 +1,26 @@
package com.cisd.tms.modules.auth.controller;
import com.cisd.tms.common.api.ApiResponse;
import com.cisd.tms.modules.auth.dto.ChangePasswordRequest;
import com.cisd.tms.modules.auth.dto.CurrentUserResponse;
import com.cisd.tms.modules.auth.dto.LoginRequest;
import com.cisd.tms.modules.auth.dto.LoginResponse;
import com.cisd.tms.modules.auth.dto.UkeyBindRequest;
import com.cisd.tms.modules.auth.security.RequireAuthLevel;
import com.cisd.tms.modules.auth.security.RequireRole;
import com.cisd.tms.modules.auth.service.AuthAdminService;
import com.cisd.tms.modules.auth.service.AuthService;
import com.cisd.tms.modules.mk.dto.UKeySignDTO;
import com.cisd.tms.modules.mk.dto.UKeySignResult;
import com.cisd.tms.security.internal.InternalApiAuthInterceptor;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
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.RequestHeader;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -22,23 +30,108 @@ import org.springframework.web.bind.annotation.RestController;
public class AuthController {
private final AuthService authService;
private final AuthAdminService authAdminService;
public AuthController(AuthService authService) {
public AuthController(AuthService authService, AuthAdminService authAdminService) {
this.authService = authService;
this.authAdminService = authAdminService;
}
@PostMapping("/login")
@Operation(summary = "内部用户登录", description = "校验用户名和密码,返回访问令牌及过期时间。")
@Operation(summary = "内部用户登录", description = "校验角色口令,可选校验 UKey 序列号,返回访问令牌和认证等级。")
public ApiResponse<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
return ApiResponse.success(authService.login(request));
}
@GetMapping("/me")
@Operation(summary = "查询当前用户", description = "根据请求头中的用户标识返回当前登录用户信息。")
public ApiResponse<CurrentUserResponse> me(
@Parameter(description = "当前用户标识,来自内部鉴权链路透传的 X-User 请求头")
@RequestHeader(value = "X-User", required = false) String user
@Operation(summary = "查询当前用户", description = "根据内部鉴权链路透传的当前角色标识返回当前登录用户信息。")
public ApiResponse<CurrentUserResponse> me(HttpServletRequest request) {
String user = (String) request.getAttribute(com.cisd.tms.security.internal.InternalApiAuthInterceptor.ATTR_ROLE_CODE);
String sessionToken = (String) request.getAttribute(com.cisd.tms.security.internal.InternalApiAuthInterceptor.ATTR_SESSION_TOKEN);
return ApiResponse.success(authService.me(user, sessionToken));
}
@PostMapping("/logout")
@Operation(summary = "退出当前会话", description = "使当前内部管理端会话失效。")
public ApiResponse<Void> logout(HttpServletRequest request) {
authService.logout((String) request.getAttribute(InternalApiAuthInterceptor.ATTR_SESSION_TOKEN));
return ApiResponse.success();
}
@PostMapping("/change-password")
@Operation(summary = "修改当前角色口令", description = "基于当前登录会话校验并更新角色口令。")
public ApiResponse<Void> changePassword(@Valid @RequestBody ChangePasswordRequest request, HttpServletRequest httpRequest) {
authService.changePassword(
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_SESSION_TOKEN),
request.getCurrentPassword(),
request.getNewPassword()
);
return ApiResponse.success();
}
@PostMapping("/roles/{roleCode}/enable")
@Operation(summary = "启用角色", description = "仅允许密钥管理员 FULL 会话启用目标角色。")
@RequireRole("KEY_ADMIN")
@RequireAuthLevel("FULL")
public ApiResponse<Void> enableRole(@PathVariable("roleCode") String roleCode, HttpServletRequest request) {
authAdminService.enableRole(
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL),
roleCode
);
return ApiResponse.success();
}
@PostMapping("/roles/{roleCode}/reset-password")
@Operation(summary = "重置角色密码", description = "仅允许密钥管理员 FULL 会话重置目标角色密码。")
@RequireRole("KEY_ADMIN")
@RequireAuthLevel("FULL")
public ApiResponse<Void> resetPassword(@PathVariable("roleCode") String roleCode, HttpServletRequest request) {
authAdminService.resetPassword(
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL),
roleCode
);
return ApiResponse.success();
}
@PostMapping("/roles/{roleCode}/ukeys/bind")
@Operation(summary = "绑定角色 UKey", description = "仅允许密钥管理员 FULL 会话绑定或覆盖目标角色槽位上的 UKey。")
@RequireRole("KEY_ADMIN")
@RequireAuthLevel("FULL")
public ApiResponse<Void> bindUkey(
@PathVariable("roleCode") String roleCode,
@Valid @RequestBody UkeyBindRequest request,
HttpServletRequest httpRequest
) {
return ApiResponse.success(authService.me(user));
authAdminService.bindIssuedUkey(
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL),
roleCode,
request.getSlotNo(),
request.getUkeySerial(),
request.getUkeyPubkey(),
request.getUid(),
request.getRid(),
request.getIssuerSign()
);
return ApiResponse.success();
}
@PostMapping("/roles/{roleCode}/ukeys/issue-sign")
@Operation(summary = "生成绑定用 UKey 发行签名", description = "按旧管理端绑定流程为目标角色的 UKey 信息出具发行签名。")
@RequireRole("KEY_ADMIN")
@RequireAuthLevel("FULL")
public ApiResponse<UKeySignResult> issueUkeyBindingSign(
@PathVariable("roleCode") String roleCode,
@RequestBody UKeySignDTO request,
HttpServletRequest httpRequest
) {
return ApiResponse.success(authAdminService.issueUkeyBindingSign(
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL),
roleCode,
request
));
}
}
@@ -0,0 +1,50 @@
package com.cisd.tms.modules.auth.controller;
import com.cisd.tms.common.api.ApiResponse;
import com.cisd.tms.modules.auth.dto.CompatPasswordLoginRequest;
import com.cisd.tms.modules.auth.dto.CompatUkeyLoginRequest;
import com.cisd.tms.modules.auth.dto.LoginResponse;
import com.cisd.tms.modules.auth.dto.UkeyLoginRandomResponse;
import com.cisd.tms.modules.auth.service.CompatAuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1/auth")
@Tag(name = "认证兼容接口", description = "兼容旧管理端的口令登录、UKey 登录与随机数接口")
public class CompatAuthController {
private final CompatAuthService compatAuthService;
public CompatAuthController(CompatAuthService compatAuthService) {
this.compatAuthService = compatAuthService;
}
@GetMapping("/ukey-login/randoms")
@Operation(summary = "生成 UKey 登录随机数", description = "兼容旧登录流程,为指定角色生成一组待签名随机数。")
public ApiResponse<UkeyLoginRandomResponse> issueUkeyLoginRandoms(
@RequestParam("role") String role,
@RequestParam(value = "count", required = false) Integer count
) {
return ApiResponse.success(compatAuthService.issueUkeyLoginRandoms(role, count));
}
@PostMapping("/password-login")
@Operation(summary = "兼容口令登录", description = "兼容旧管理端的角色口令登录语义,底层复用当前会话体系。")
public ApiResponse<LoginResponse> passwordLogin(@Valid @RequestBody CompatPasswordLoginRequest request) {
return ApiResponse.success(compatAuthService.passwordLogin(request));
}
@PostMapping("/ukey-login")
@Operation(summary = "兼容 UKey 登录", description = "兼容旧管理端的 UKey 登录语义,校验发行签名、随机数和登录签名。")
public ApiResponse<LoginResponse> ukeyLogin(@Valid @RequestBody CompatUkeyLoginRequest request) {
return ApiResponse.success(compatAuthService.ukeyLogin(request));
}
}
@@ -0,0 +1,32 @@
package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
@Schema(description = "修改当前角色口令请求")
public class ChangePasswordRequest {
@NotBlank(message = "currentPassword is required")
@Schema(description = "当前口令", example = "12345678")
private String currentPassword;
@NotBlank(message = "newPassword is required")
@Schema(description = "新口令", example = "87654321")
private String newPassword;
public String getCurrentPassword() {
return currentPassword;
}
public void setCurrentPassword(String currentPassword) {
this.currentPassword = currentPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
@@ -0,0 +1,32 @@
package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
@Schema(description = "兼容旧管理端的口令登录请求")
public class CompatPasswordLoginRequest {
@NotBlank(message = "role is required")
@Schema(description = "角色标识,兼容旧角色名称", example = "auditadmin")
private String role;
@NotBlank(message = "password is required")
@Schema(description = "登录口令", example = "12345678")
private String password;
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -0,0 +1,132 @@
package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
@Schema(description = "兼容旧管理端的 UKey 登录请求")
public class CompatUkeyLoginRequest {
@NotBlank(message = "role is required")
@Schema(description = "角色标识,兼容旧角色名称", example = "keyadmin")
private String role;
@NotBlank(message = "password is required")
@Schema(description = "登录口令", example = "12345678")
private String password;
@Valid
@NotEmpty(message = "authInfo is required")
@Schema(description = "UKey 登录认证材料")
private List<LoginAuthInfo> authInfo;
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<LoginAuthInfo> getAuthInfo() {
return authInfo;
}
public void setAuthInfo(List<LoginAuthInfo> authInfo) {
this.authInfo = authInfo;
}
@Schema(description = "单个 UKey 登录认证项")
public static class LoginAuthInfo {
@NotBlank(message = "pubKey is required")
private String pubKey;
@NotBlank(message = "uid is required")
private String uid;
@NotBlank(message = "rid is required")
private String rid;
@NotBlank(message = "ra is required")
private String ra;
@NotBlank(message = "rb is required")
private String rb;
@NotBlank(message = "issueSign is required")
private String issueSign;
@NotBlank(message = "loginSignData is required")
private String loginSignData;
@NotBlank(message = "loginSign is required")
private String loginSign;
public String getPubKey() {
return pubKey;
}
public void setPubKey(String pubKey) {
this.pubKey = pubKey;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getRid() {
return rid;
}
public void setRid(String rid) {
this.rid = rid;
}
public String getRa() {
return ra;
}
public void setRa(String ra) {
this.ra = ra;
}
public String getRb() {
return rb;
}
public void setRb(String rb) {
this.rb = rb;
}
public String getIssueSign() {
return issueSign;
}
public void setIssueSign(String issueSign) {
this.issueSign = issueSign;
}
public String getLoginSignData() {
return loginSignData;
}
public void setLoginSignData(String loginSignData) {
this.loginSignData = loginSignData;
}
public String getLoginSign() {
return loginSign;
}
public void setLoginSign(String loginSign) {
this.loginSign = loginSign;
}
}
}
@@ -11,6 +11,10 @@ public class CurrentUserResponse {
private String displayName;
@Schema(description = "角色标识", example = "ADMIN")
private String role;
@Schema(description = "当前会话等级", example = "FULL")
private String authLevel;
@Schema(description = "是否需要强制修改密码")
private Boolean needChangePassword;
public String getUsername() {
return username;
@@ -35,4 +39,20 @@ public class CurrentUserResponse {
public void setRole(String role) {
this.role = role;
}
public String getAuthLevel() {
return authLevel;
}
public void setAuthLevel(String authLevel) {
this.authLevel = authLevel;
}
public Boolean getNeedChangePassword() {
return needChangePassword;
}
public void setNeedChangePassword(Boolean needChangePassword) {
this.needChangePassword = needChangePassword;
}
}
@@ -2,24 +2,28 @@ package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import java.util.List;
@Schema(description = "内部登录请求")
public class LoginRequest {
@NotBlank(message = "username is required")
@Schema(description = "登录用户名", example = "admin")
private String username;
@NotBlank(message = "roleCode is required")
@Schema(description = "角色编码", example = "KEY_ADMIN")
private String roleCode;
@NotBlank(message = "password is required")
@Schema(description = "登录密码", example = "P@ssw0rd")
private String password;
public String getUsername() {
return username;
@Schema(description = "UKey 序列号列表,完整登录时需传入角色要求数量的序列号")
private List<@NotBlank(message = "ukey serial must not be blank") String> ukeySerials;
public String getRoleCode() {
return roleCode;
}
public void setUsername(String username) {
this.username = username;
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getPassword() {
@@ -29,4 +33,12 @@ public class LoginRequest {
public void setPassword(String password) {
this.password = password;
}
public List<String> getUkeySerials() {
return ukeySerials;
}
public void setUkeySerials(List<String> ukeySerials) {
this.ukeySerials = ukeySerials;
}
}
@@ -5,19 +5,23 @@ import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "内部登录响应")
public class LoginResponse {
@Schema(description = "登录用户名", example = "admin")
private String username;
@Schema(description = "角色编码", example = "KEY_ADMIN")
private String roleCode;
@Schema(description = "访问令牌")
private String token;
@Schema(description = "认证等级", example = "FULL")
private String authLevel;
@Schema(description = "令牌过期时间", example = "2026-03-11T18:00:00+08:00")
private String expiresAt;
@Schema(description = "是否需要首次修改密码")
private Boolean needChangePassword;
public String getUsername() {
return username;
public String getRoleCode() {
return roleCode;
}
public void setUsername(String username) {
this.username = username;
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getToken() {
@@ -28,6 +32,14 @@ public class LoginResponse {
this.token = token;
}
public String getAuthLevel() {
return authLevel;
}
public void setAuthLevel(String authLevel) {
this.authLevel = authLevel;
}
public String getExpiresAt() {
return expiresAt;
}
@@ -35,4 +47,12 @@ public class LoginResponse {
public void setExpiresAt(String expiresAt) {
this.expiresAt = expiresAt;
}
public Boolean getNeedChangePassword() {
return needChangePassword;
}
public void setNeedChangePassword(Boolean needChangePassword) {
this.needChangePassword = needChangePassword;
}
}
@@ -0,0 +1,81 @@
package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Schema(description = "UKey 绑定请求")
public class UkeyBindRequest {
@NotNull(message = "slotNo is required")
@Schema(description = "角色 UKey 槽位号", example = "1")
private Integer slotNo;
@NotBlank(message = "ukeySerial is required")
@Schema(description = "UKey 序列号", example = "UK-001")
private String ukeySerial;
@NotBlank(message = "ukeyPubkey is required")
@Schema(description = "UKey 公钥")
private String ukeyPubkey;
@NotBlank(message = "uid is required")
@Schema(description = "UKey 认证信息 uid", example = "1")
private String uid;
@NotBlank(message = "rid is required")
@Schema(description = "UKey 认证信息 rid", example = "RID-001")
private String rid;
@NotBlank(message = "issuerSign is required")
@Schema(description = "认证公钥签名值")
private String issuerSign;
public Integer getSlotNo() {
return slotNo;
}
public void setSlotNo(Integer slotNo) {
this.slotNo = slotNo;
}
public String getUkeySerial() {
return ukeySerial;
}
public void setUkeySerial(String ukeySerial) {
this.ukeySerial = ukeySerial;
}
public String getUkeyPubkey() {
return ukeyPubkey;
}
public void setUkeyPubkey(String ukeyPubkey) {
this.ukeyPubkey = ukeyPubkey;
}
public String getIssuerSign() {
return issuerSign;
}
public void setIssuerSign(String issuerSign) {
this.issuerSign = issuerSign;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getRid() {
return rid;
}
public void setRid(String rid) {
this.rid = rid;
}
}
@@ -0,0 +1,30 @@
package com.cisd.tms.modules.auth.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
@Schema(description = "UKey 登录随机数响应")
public class UkeyLoginRandomResponse {
@Schema(description = "标准化后的角色编码", example = "SUPER_ADMIN")
private String roleCode;
@Schema(description = "供 UKey 登录签名使用的随机数列表")
private List<String> randoms;
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public List<String> getRandoms() {
return randoms;
}
public void setRandoms(List<String> randoms) {
this.randoms = randoms;
}
}
@@ -0,0 +1,73 @@
package com.cisd.tms.modules.auth.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cisd.tms.infrastructure.persistence.entity.BaseEntity;
import java.time.LocalDateTime;
@TableName("tms_auth_session")
public class AuthSessionEntity extends BaseEntity {
private String sessionToken;
private String roleCode;
private String authLevel;
private LocalDateTime issuedAt;
private LocalDateTime lastActiveAt;
private LocalDateTime expiresAt;
private LocalDateTime logoutAt;
public String getSessionToken() {
return sessionToken;
}
public void setSessionToken(String sessionToken) {
this.sessionToken = sessionToken;
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getAuthLevel() {
return authLevel;
}
public void setAuthLevel(String authLevel) {
this.authLevel = authLevel;
}
public LocalDateTime getIssuedAt() {
return issuedAt;
}
public void setIssuedAt(LocalDateTime issuedAt) {
this.issuedAt = issuedAt;
}
public LocalDateTime getLastActiveAt() {
return lastActiveAt;
}
public void setLastActiveAt(LocalDateTime lastActiveAt) {
this.lastActiveAt = lastActiveAt;
}
public LocalDateTime getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(LocalDateTime expiresAt) {
this.expiresAt = expiresAt;
}
public LocalDateTime getLogoutAt() {
return logoutAt;
}
public void setLogoutAt(LocalDateTime logoutAt) {
this.logoutAt = logoutAt;
}
}
@@ -0,0 +1,109 @@
package com.cisd.tms.modules.auth.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cisd.tms.infrastructure.persistence.entity.BaseEntity;
import java.time.LocalDateTime;
@TableName("tms_role_account")
public class RoleAccountEntity extends BaseEntity {
private String roleCode;
private String displayName;
private Integer requiredUkeyCount;
private String passwordHash;
private String passwordSalt;
private String status;
private Boolean needChangePassword;
private Integer failedCount;
private LocalDateTime lockedUntil;
private LocalDateTime lastLoginAt;
private LocalDateTime lastActiveAt;
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Integer getRequiredUkeyCount() {
return requiredUkeyCount;
}
public void setRequiredUkeyCount(Integer requiredUkeyCount) {
this.requiredUkeyCount = requiredUkeyCount;
}
public String getPasswordHash() {
return passwordHash;
}
public void setPasswordHash(String passwordHash) {
this.passwordHash = passwordHash;
}
public String getPasswordSalt() {
return passwordSalt;
}
public void setPasswordSalt(String passwordSalt) {
this.passwordSalt = passwordSalt;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Boolean getNeedChangePassword() {
return needChangePassword;
}
public void setNeedChangePassword(Boolean needChangePassword) {
this.needChangePassword = needChangePassword;
}
public Integer getFailedCount() {
return failedCount;
}
public void setFailedCount(Integer failedCount) {
this.failedCount = failedCount;
}
public LocalDateTime getLockedUntil() {
return lockedUntil;
}
public void setLockedUntil(LocalDateTime lockedUntil) {
this.lockedUntil = lockedUntil;
}
public LocalDateTime getLastLoginAt() {
return lastLoginAt;
}
public void setLastLoginAt(LocalDateTime lastLoginAt) {
this.lastLoginAt = lastLoginAt;
}
public LocalDateTime getLastActiveAt() {
return lastActiveAt;
}
public void setLastActiveAt(LocalDateTime lastActiveAt) {
this.lastActiveAt = lastActiveAt;
}
}
@@ -0,0 +1,82 @@
package com.cisd.tms.modules.auth.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cisd.tms.infrastructure.persistence.entity.BaseEntity;
import java.time.LocalDateTime;
@TableName("tms_role_ukey_binding")
public class RoleUkeyBindingEntity extends BaseEntity {
private String roleCode;
private Integer slotNo;
private String ukeySerial;
private String ukeyPubkey;
private String issuerSign;
private String status;
private LocalDateTime boundAt;
private LocalDateTime unboundAt;
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public Integer getSlotNo() {
return slotNo;
}
public void setSlotNo(Integer slotNo) {
this.slotNo = slotNo;
}
public String getUkeySerial() {
return ukeySerial;
}
public void setUkeySerial(String ukeySerial) {
this.ukeySerial = ukeySerial;
}
public String getUkeyPubkey() {
return ukeyPubkey;
}
public void setUkeyPubkey(String ukeyPubkey) {
this.ukeyPubkey = ukeyPubkey;
}
public String getIssuerSign() {
return issuerSign;
}
public void setIssuerSign(String issuerSign) {
this.issuerSign = issuerSign;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getBoundAt() {
return boundAt;
}
public void setBoundAt(LocalDateTime boundAt) {
this.boundAt = boundAt;
}
public LocalDateTime getUnboundAt() {
return unboundAt;
}
public void setUnboundAt(LocalDateTime unboundAt) {
this.unboundAt = unboundAt;
}
}
@@ -0,0 +1,6 @@
package com.cisd.tms.modules.auth.enums;
public enum AuthLevel {
LIMITED,
FULL
}
@@ -0,0 +1,7 @@
package com.cisd.tms.modules.auth.enums;
public enum RoleAccountStatus {
UNENABLED,
ACTIVE,
LOCKED
}
@@ -0,0 +1,30 @@
package com.cisd.tms.modules.auth.enums;
public enum RoleCode {
SUPER_ADMIN("SUPER_ADMIN", "超级管理员", 3),
KEY_ADMIN("KEY_ADMIN", "密钥管理员", 2),
AUDIT_ADMIN("AUDIT_ADMIN", "审计管理员", 1),
OPS_ADMIN("OPS_ADMIN", "运维管理员", 1);
private final String code;
private final String displayName;
private final int requiredUkeyCount;
RoleCode(String code, String displayName, int requiredUkeyCount) {
this.code = code;
this.displayName = displayName;
this.requiredUkeyCount = requiredUkeyCount;
}
public String getCode() {
return code;
}
public String getDisplayName() {
return displayName;
}
public int getRequiredUkeyCount() {
return requiredUkeyCount;
}
}
@@ -0,0 +1,12 @@
package com.cisd.tms.modules.auth.mapper;
import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX;
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface AuthSessionMapper extends BaseMapperX<AuthSessionEntity> {
AuthSessionEntity selectBySessionToken(@Param("sessionToken") String sessionToken);
}
@@ -0,0 +1,12 @@
package com.cisd.tms.modules.auth.mapper;
import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX;
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface RoleAccountMapper extends BaseMapperX<RoleAccountEntity> {
RoleAccountEntity selectByRoleCode(@Param("roleCode") String roleCode);
}
@@ -0,0 +1,15 @@
package com.cisd.tms.modules.auth.mapper;
import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface RoleUkeyBindingMapper extends BaseMapperX<RoleUkeyBindingEntity> {
RoleUkeyBindingEntity selectActiveByRoleCodeAndSlotNo(@Param("roleCode") String roleCode, @Param("slotNo") Integer slotNo);
List<RoleUkeyBindingEntity> selectActiveByRoleCode(@Param("roleCode") String roleCode);
}
@@ -0,0 +1,13 @@
package com.cisd.tms.modules.auth.repository;
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
import java.util.Optional;
public interface AuthSessionRepository {
Optional<AuthSessionEntity> findBySessionToken(String sessionToken);
void save(AuthSessionEntity entity);
void update(AuthSessionEntity entity);
}
@@ -0,0 +1,13 @@
package com.cisd.tms.modules.auth.repository;
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
import java.util.Optional;
public interface RoleAccountRepository {
Optional<RoleAccountEntity> findByRoleCode(String roleCode);
void save(RoleAccountEntity entity);
void update(RoleAccountEntity entity);
}
@@ -0,0 +1,16 @@
package com.cisd.tms.modules.auth.repository;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import java.util.List;
import java.util.Optional;
public interface RoleUkeyBindingRepository {
Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndSlotNo(String roleCode, Integer slotNo);
List<RoleUkeyBindingEntity> findActiveByRoleCode(String roleCode);
void save(RoleUkeyBindingEntity entity);
void update(RoleUkeyBindingEntity entity);
}
@@ -0,0 +1,32 @@
package com.cisd.tms.modules.auth.repository.impl;
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
import com.cisd.tms.modules.auth.mapper.AuthSessionMapper;
import com.cisd.tms.modules.auth.repository.AuthSessionRepository;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class AuthSessionRepositoryImpl implements AuthSessionRepository {
private final AuthSessionMapper authSessionMapper;
public AuthSessionRepositoryImpl(AuthSessionMapper authSessionMapper) {
this.authSessionMapper = authSessionMapper;
}
@Override
public Optional<AuthSessionEntity> findBySessionToken(String sessionToken) {
return Optional.ofNullable(authSessionMapper.selectBySessionToken(sessionToken));
}
@Override
public void save(AuthSessionEntity entity) {
authSessionMapper.insert(entity);
}
@Override
public void update(AuthSessionEntity entity) {
authSessionMapper.updateById(entity);
}
}
@@ -0,0 +1,32 @@
package com.cisd.tms.modules.auth.repository.impl;
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
import com.cisd.tms.modules.auth.mapper.RoleAccountMapper;
import com.cisd.tms.modules.auth.repository.RoleAccountRepository;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class RoleAccountRepositoryImpl implements RoleAccountRepository {
private final RoleAccountMapper roleAccountMapper;
public RoleAccountRepositoryImpl(RoleAccountMapper roleAccountMapper) {
this.roleAccountMapper = roleAccountMapper;
}
@Override
public Optional<RoleAccountEntity> findByRoleCode(String roleCode) {
return Optional.ofNullable(roleAccountMapper.selectByRoleCode(roleCode));
}
@Override
public void save(RoleAccountEntity entity) {
roleAccountMapper.insert(entity);
}
@Override
public void update(RoleAccountEntity entity) {
roleAccountMapper.updateById(entity);
}
}
@@ -0,0 +1,38 @@
package com.cisd.tms.modules.auth.repository.impl;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import com.cisd.tms.modules.auth.mapper.RoleUkeyBindingMapper;
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class RoleUkeyBindingRepositoryImpl implements RoleUkeyBindingRepository {
private final RoleUkeyBindingMapper roleUkeyBindingMapper;
public RoleUkeyBindingRepositoryImpl(RoleUkeyBindingMapper roleUkeyBindingMapper) {
this.roleUkeyBindingMapper = roleUkeyBindingMapper;
}
@Override
public Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndSlotNo(String roleCode, Integer slotNo) {
return Optional.ofNullable(roleUkeyBindingMapper.selectActiveByRoleCodeAndSlotNo(roleCode, slotNo));
}
@Override
public List<RoleUkeyBindingEntity> findActiveByRoleCode(String roleCode) {
return roleUkeyBindingMapper.selectActiveByRoleCode(roleCode);
}
@Override
public void save(RoleUkeyBindingEntity entity) {
roleUkeyBindingMapper.insert(entity);
}
@Override
public void update(RoleUkeyBindingEntity entity) {
roleUkeyBindingMapper.updateById(entity);
}
}
@@ -0,0 +1,68 @@
package com.cisd.tms.modules.auth.security;
import com.cisd.tms.common.api.ApiResponse;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.util.HttpResponseUtil;
import com.cisd.tms.security.internal.InternalApiAuthInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class InternalAuthorizationInterceptor implements HandlerInterceptor {
private final ObjectMapper objectMapper;
public InternalAuthorizationInterceptor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod handlerMethod)) {
return true;
}
RequireRole requireRole = findAnnotation(handlerMethod, RequireRole.class);
if (requireRole != null) {
String currentRole = (String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE);
if (!requireRole.value().equals(currentRole)) {
writeForbidden(response, "role not allowed");
return false;
}
}
RequireAuthLevel requireAuthLevel = findAnnotation(handlerMethod, RequireAuthLevel.class);
if (requireAuthLevel != null) {
String currentAuthLevel = (String) request.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL);
if (!requireAuthLevel.value().equals(currentAuthLevel)) {
writeForbidden(response, "auth level not allowed");
return false;
}
}
return true;
}
private <T extends java.lang.annotation.Annotation> T findAnnotation(HandlerMethod handlerMethod, Class<T> annotationType) {
T methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getMethod(), annotationType);
if (methodAnnotation != null) {
return methodAnnotation;
}
return AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), annotationType);
}
private void writeForbidden(HttpServletResponse response, String message) throws IOException {
HttpResponseUtil.writeJson(
response,
HttpServletResponse.SC_FORBIDDEN,
ApiResponse.fail(ErrorCode.UNAUTHORIZED.getCode(), message),
objectMapper
);
}
}
@@ -0,0 +1,13 @@
package com.cisd.tms.modules.auth.security;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireAuthLevel {
String value();
}
@@ -0,0 +1,13 @@
package com.cisd.tms.modules.auth.security;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireRole {
String value();
}
@@ -0,0 +1,276 @@
package com.cisd.tms.modules.auth.service;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.exception.BizException;
import com.cisd.tms.integration.crypto.pcie.service.MockPcieCryptoService;
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import com.cisd.tms.modules.auth.enums.AuthLevel;
import com.cisd.tms.modules.auth.enums.RoleAccountStatus;
import com.cisd.tms.modules.auth.enums.RoleCode;
import com.cisd.tms.modules.auth.repository.RoleAccountRepository;
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
import com.cisd.tms.common.util.TraceIdUtil;
import com.cisd.tms.modules.mk.config.MasterKeyInitProperties;
import com.cisd.tms.modules.mk.dto.UKeySignDTO;
import com.cisd.tms.modules.mk.dto.UKeySignEntity;
import com.cisd.tms.modules.mk.dto.UKeySignResult;
import com.cisd.tms.modules.mk.service.LmkService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Supplier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AuthAdminService {
static final String DEFAULT_PASSWORD = "12345678";
private final RoleAccountRepository roleAccountRepository;
private final RoleUkeyBindingRepository roleUkeyBindingRepository;
private final PasswordHasher passwordHasher;
private final LmkService lmkService;
private final ObjectMapper objectMapper;
private final Clock clock;
private final Supplier<String> saltSupplier;
@Autowired
public AuthAdminService(
RoleAccountRepository roleAccountRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
PasswordHasher passwordHasher,
LmkService lmkService,
ObjectMapper objectMapper
) {
this(
roleAccountRepository,
roleUkeyBindingRepository,
passwordHasher,
lmkService,
objectMapper,
Clock.systemUTC(),
() -> UUID.randomUUID().toString().replace("-", "")
);
}
AuthAdminService(
RoleAccountRepository roleAccountRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
LmkService lmkService,
PasswordHasher passwordHasher,
Clock clock,
Supplier<String> saltSupplier
) {
this(
roleAccountRepository,
roleUkeyBindingRepository,
passwordHasher,
lmkService,
new ObjectMapper(),
clock,
saltSupplier
);
}
AuthAdminService(
RoleAccountRepository roleAccountRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
PasswordHasher passwordHasher,
Clock clock,
Supplier<String> saltSupplier
) {
this(
roleAccountRepository,
roleUkeyBindingRepository,
new LmkService(new MockPcieCryptoService(), new MasterKeyInitProperties()),
passwordHasher,
clock,
saltSupplier
);
}
AuthAdminService(
RoleAccountRepository roleAccountRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
PasswordHasher passwordHasher,
LmkService lmkService,
ObjectMapper objectMapper,
Clock clock,
Supplier<String> saltSupplier
) {
this.roleAccountRepository = roleAccountRepository;
this.roleUkeyBindingRepository = roleUkeyBindingRepository;
this.passwordHasher = passwordHasher;
this.lmkService = lmkService;
this.objectMapper = objectMapper;
this.clock = clock;
this.saltSupplier = saltSupplier;
}
public void enableRole(String operatorRoleCode, String operatorAuthLevel, String targetRoleCode) {
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
RoleAccountEntity target = loadRole(targetRoleCode);
target.setStatus(RoleAccountStatus.ACTIVE.name());
target.setNeedChangePassword(Boolean.TRUE);
target.setLockedUntil(null);
target.setFailedCount(0);
roleAccountRepository.update(target);
}
public void resetPassword(String operatorRoleCode, String operatorAuthLevel, String targetRoleCode) {
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
RoleAccountEntity target = loadRole(targetRoleCode);
String newSalt = saltSupplier.get();
target.setPasswordSalt(newSalt);
target.setPasswordHash(passwordHasher.hash(DEFAULT_PASSWORD, newSalt));
target.setStatus(RoleAccountStatus.ACTIVE.name());
target.setNeedChangePassword(Boolean.TRUE);
target.setFailedCount(0);
target.setLockedUntil(null);
roleAccountRepository.update(target);
}
public void bindUkey(
String operatorRoleCode,
String operatorAuthLevel,
String targetRoleCode,
Integer slotNo,
String ukeySerial,
String ukeyPubkey,
String issuerSign
) {
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
RoleCode targetRole = resolveRoleCode(targetRoleCode);
if (slotNo == null || slotNo < 1 || slotNo > targetRole.getRequiredUkeyCount()) {
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "slotNo exceeds role ukey requirement");
}
RoleUkeyBindingEntity binding = roleUkeyBindingRepository
.findActiveByRoleCodeAndSlotNo(targetRoleCode, slotNo)
.orElseGet(RoleUkeyBindingEntity::new);
if (binding.getId() == null) {
binding.setId((long) Math.abs(Objects.hash(targetRoleCode, slotNo, ukeySerial, TraceIdUtil.newTraceId())));
binding.setRoleCode(targetRoleCode);
binding.setSlotNo(slotNo);
binding.setStatus("ACTIVE");
applyBinding(binding, ukeySerial, ukeyPubkey, issuerSign);
roleUkeyBindingRepository.save(binding);
return;
}
applyBinding(binding, ukeySerial, ukeyPubkey, issuerSign);
roleUkeyBindingRepository.update(binding);
}
public void bindIssuedUkey(
String operatorRoleCode,
String operatorAuthLevel,
String targetRoleCode,
Integer slotNo,
String ukeySerial,
String ukeyPubkey,
String uid,
String rid,
String issuerSign
) {
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
resolveRoleCode(targetRoleCode);
verifyIssuerSignature(targetRoleCode, ukeyPubkey, uid, rid, issuerSign);
bindUkey(operatorRoleCode, operatorAuthLevel, targetRoleCode, slotNo, ukeySerial, ukeyPubkey, issuerSign);
}
public UKeySignResult issueUkeyBindingSign(
String operatorRoleCode,
String operatorAuthLevel,
String targetRoleCode,
UKeySignDTO request
) {
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
RoleCode targetRole = resolveRoleCode(targetRoleCode);
String legacyRole = toLegacyRole(targetRole);
String authKeyPair = lmkService.exportIkPublicKeyHex();
UKeySignDTO dto = new UKeySignDTO();
dto.setPubKey(request.getPubKey());
dto.setRole(legacyRole);
dto.setUid(request.getUid());
dto.setRid(request.getRid());
dto.setExtra(request.getExtra());
String signValue = lmkService.signIk(toIssuePayload(dto, authKeyPair));
String extra = "";
return UKeySignResult.builder().sign(signValue).component(extra).build();
}
private void applyBinding(RoleUkeyBindingEntity binding, String ukeySerial, String ukeyPubkey, String issuerSign) {
binding.setUkeySerial(ukeySerial);
binding.setUkeyPubkey(ukeyPubkey);
binding.setIssuerSign(issuerSign);
binding.setStatus("ACTIVE");
binding.setBoundAt(now());
binding.setUnboundAt(null);
}
private void requireKeyAdminFull(String operatorRoleCode, String operatorAuthLevel) {
if (!RoleCode.KEY_ADMIN.getCode().equals(operatorRoleCode) || !AuthLevel.FULL.name().equals(operatorAuthLevel)) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "operation requires KEY_ADMIN FULL session");
}
}
private RoleAccountEntity loadRole(String roleCode) {
resolveRoleCode(roleCode);
return roleAccountRepository.findByRoleCode(roleCode)
.orElseThrow(() -> new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "target role account not found"));
}
private RoleCode resolveRoleCode(String roleCode) {
return List.of(RoleCode.values()).stream()
.filter(item -> item.getCode().equals(roleCode))
.findFirst()
.orElseThrow(() -> new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "invalid roleCode"));
}
private LocalDateTime now() {
return LocalDateTime.ofInstant(clock.instant(), ZoneOffset.UTC);
}
private void verifyIssuerSignature(String targetRoleCode, String ukeyPubkey, String uid, String rid, String issuerSign) {
try {
UKeySignDTO dto = new UKeySignDTO();
dto.setPubKey(ukeyPubkey);
dto.setRole(toLegacyRole(resolveRoleCode(targetRoleCode)));
dto.setUid(uid);
dto.setRid(rid);
String authKeyPair = lmkService.exportIkPublicKeyHex();
lmkService.verifyIk(toIssuePayload(dto, authKeyPair), issuerSign);
} catch (BizException ex) {
throw ex;
} catch (RuntimeException ex) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey issuer signature verification failed");
}
}
private String toIssuePayload(UKeySignDTO dto, String authKeyPair) {
try {
return objectMapper.writeValueAsString(UKeySignEntity.getInstance(dto, authKeyPair));
} catch (JsonProcessingException ex) {
throw new IllegalStateException("serialize ukey issue payload failed", ex);
}
}
private String toLegacyRole(RoleCode roleCode) {
return switch (roleCode) {
case SUPER_ADMIN -> "superadmin";
case KEY_ADMIN -> "keyadmin";
case AUDIT_ADMIN -> "auditadmin";
case OPS_ADMIN -> "configadmin";
};
}
}
@@ -1,33 +1,126 @@
package com.cisd.tms.modules.auth.service;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.exception.BizException;
import com.cisd.tms.modules.auth.dto.CurrentUserResponse;
import com.cisd.tms.modules.auth.dto.LoginRequest;
import com.cisd.tms.modules.auth.dto.LoginResponse;
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
import com.cisd.tms.modules.auth.entity.AuthUserEntity;
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import com.cisd.tms.modules.auth.enums.AuthLevel;
import com.cisd.tms.modules.auth.enums.RoleAccountStatus;
import com.cisd.tms.modules.auth.repository.AuthUserRepository;
import com.cisd.tms.modules.auth.repository.AuthSessionRepository;
import com.cisd.tms.modules.auth.repository.RoleAccountRepository;
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.function.Supplier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
private final AuthUserRepository authUserRepository;
private static final int MAX_FAILED_ATTEMPTS = 5;
private static final int IDLE_TIMEOUT_MINUTES = 10;
public AuthService(AuthUserRepository authUserRepository) {
private final RoleAccountRepository roleAccountRepository;
private final AuthUserRepository authUserRepository;
private final AuthSessionRepository authSessionRepository;
private final RoleUkeyBindingRepository roleUkeyBindingRepository;
private final PasswordHasher passwordHasher;
private final Clock clock;
private final Supplier<String> tokenSupplier;
@Autowired
public AuthService(
RoleAccountRepository roleAccountRepository,
AuthUserRepository authUserRepository,
AuthSessionRepository authSessionRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
PasswordHasher passwordHasher
) {
this(
roleAccountRepository,
authUserRepository,
authSessionRepository,
roleUkeyBindingRepository,
passwordHasher,
Clock.systemUTC(),
() -> "tms-" + UUID.randomUUID()
);
}
AuthService(
RoleAccountRepository roleAccountRepository,
AuthUserRepository authUserRepository,
AuthSessionRepository authSessionRepository,
RoleUkeyBindingRepository roleUkeyBindingRepository,
PasswordHasher passwordHasher,
Clock clock,
Supplier<String> tokenSupplier
) {
this.roleAccountRepository = roleAccountRepository;
this.authUserRepository = authUserRepository;
this.authSessionRepository = authSessionRepository;
this.roleUkeyBindingRepository = roleUkeyBindingRepository;
this.passwordHasher = passwordHasher;
this.clock = clock;
this.tokenSupplier = tokenSupplier;
}
public LoginResponse login(LoginRequest request) {
RoleAccountEntity roleAccount = roleAccountRepository.findByRoleCode(request.getRoleCode())
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role account not found"));
validateRoleStatus(roleAccount);
if (!passwordHasher.matches(request.getPassword(), roleAccount.getPasswordSalt(), roleAccount.getPasswordHash())) {
onPasswordFailed(roleAccount);
}
resetFailureState(roleAccount);
AuthLevel authLevel = resolveAuthLevel(roleAccount, request.getUkeySerials());
AuthSessionEntity session = buildSession(roleAccount.getRoleCode(), authLevel);
authSessionRepository.save(session);
LoginResponse response = new LoginResponse();
response.setUsername(request.getUsername());
response.setToken("tms-" + UUID.randomUUID());
response.setExpiresAt(OffsetDateTime.now().plusHours(8).toString());
response.setRoleCode(roleAccount.getRoleCode());
response.setAuthLevel(authLevel.name());
response.setToken(session.getSessionToken());
response.setExpiresAt(OffsetDateTime.of(session.getExpiresAt(), ZoneOffset.UTC).toString());
response.setNeedChangePassword(Boolean.TRUE.equals(roleAccount.getNeedChangePassword()));
return response;
}
public CurrentUserResponse me(String username) {
return me(username, null);
}
public CurrentUserResponse me(String username, String sessionToken) {
String normalized = username == null || username.isBlank() ? "admin" : username;
RoleAccountEntity roleAccount = roleAccountRepository.findByRoleCode(normalized).orElse(null);
if (roleAccount != null) {
CurrentUserResponse response = new CurrentUserResponse();
response.setUsername(roleAccount.getRoleCode());
response.setDisplayName(roleAccount.getDisplayName());
response.setRole(roleAccount.getRoleCode());
AuthSessionEntity session = sessionToken == null ? null : authSessionRepository.findBySessionToken(sessionToken).orElse(null);
if (session != null) {
response.setAuthLevel(session.getAuthLevel());
}
response.setNeedChangePassword(Boolean.TRUE.equals(roleAccount.getNeedChangePassword()));
return response;
}
AuthUserEntity entity = authUserRepository.findByUsername(normalized).orElse(null);
CurrentUserResponse response = new CurrentUserResponse();
@@ -43,4 +136,114 @@ public class AuthService {
response.setRole(entity.getRole());
return response;
}
public void logout(String sessionToken) {
AuthSessionEntity session = requireActiveSession(sessionToken);
session.setLogoutAt(now());
session.setExpiresAt(now());
authSessionRepository.update(session);
}
public void changePassword(String sessionToken, String currentPassword, String newPassword) {
AuthSessionEntity session = requireActiveSession(sessionToken);
RoleAccountEntity roleAccount = roleAccountRepository.findByRoleCode(session.getRoleCode())
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role account not found"));
if (!passwordHasher.matches(currentPassword, roleAccount.getPasswordSalt(), roleAccount.getPasswordHash())) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "current password is incorrect");
}
String newSalt = UUID.randomUUID().toString().replace("-", "");
roleAccount.setPasswordSalt(newSalt);
roleAccount.setPasswordHash(passwordHasher.hash(newPassword, newSalt));
roleAccount.setNeedChangePassword(Boolean.FALSE);
roleAccount.setFailedCount(0);
roleAccount.setLockedUntil(null);
roleAccount.setStatus(RoleAccountStatus.ACTIVE.name());
roleAccountRepository.update(roleAccount);
}
private void validateRoleStatus(RoleAccountEntity roleAccount) {
if (RoleAccountStatus.UNENABLED.name().equals(roleAccount.getStatus())) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role is not enabled");
}
if (RoleAccountStatus.LOCKED.name().equals(roleAccount.getStatus()) && isStillLocked(roleAccount)) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role account is locked");
}
}
private boolean isStillLocked(RoleAccountEntity roleAccount) {
return roleAccount.getLockedUntil() == null || roleAccount.getLockedUntil().isAfter(now());
}
private void onPasswordFailed(RoleAccountEntity roleAccount) {
int failedCount = roleAccount.getFailedCount() == null ? 0 : roleAccount.getFailedCount();
failedCount++;
roleAccount.setFailedCount(failedCount);
if (failedCount >= MAX_FAILED_ATTEMPTS) {
roleAccount.setStatus(RoleAccountStatus.LOCKED.name());
roleAccount.setLockedUntil(now().plusMinutes(IDLE_TIMEOUT_MINUTES));
roleAccountRepository.update(roleAccount);
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role account is locked");
}
roleAccountRepository.update(roleAccount);
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "password is incorrect");
}
private void resetFailureState(RoleAccountEntity roleAccount) {
roleAccount.setFailedCount(0);
roleAccount.setLockedUntil(null);
roleAccount.setStatus(RoleAccountStatus.ACTIVE.name());
roleAccount.setLastLoginAt(now());
roleAccount.setLastActiveAt(now());
roleAccountRepository.update(roleAccount);
}
private AuthLevel resolveAuthLevel(RoleAccountEntity roleAccount, List<String> ukeySerials) {
if (ukeySerials == null || ukeySerials.isEmpty()) {
return AuthLevel.LIMITED;
}
Set<String> uniqueSerials = new LinkedHashSet<>(ukeySerials);
if (uniqueSerials.size() != roleAccount.getRequiredUkeyCount()) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey count does not satisfy role requirement");
}
List<RoleUkeyBindingEntity> bindings = roleUkeyBindingRepository.findActiveByRoleCode(roleAccount.getRoleCode());
if (bindings.size() != roleAccount.getRequiredUkeyCount()) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey count does not satisfy role requirement");
}
Set<String> boundSerials = bindings.stream()
.map(RoleUkeyBindingEntity::getUkeySerial)
.collect(java.util.stream.Collectors.toSet());
if (!boundSerials.containsAll(uniqueSerials)) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey verification failed");
}
return AuthLevel.FULL;
}
private AuthSessionEntity buildSession(String roleCode, AuthLevel authLevel) {
LocalDateTime issuedAt = now();
AuthSessionEntity entity = new AuthSessionEntity();
entity.setRoleCode(roleCode);
entity.setAuthLevel(authLevel.name());
entity.setSessionToken(tokenSupplier.get());
entity.setIssuedAt(issuedAt);
entity.setLastActiveAt(issuedAt);
entity.setExpiresAt(issuedAt.plusMinutes(IDLE_TIMEOUT_MINUTES));
return entity;
}
private LocalDateTime now() {
return LocalDateTime.ofInstant(clock.instant(), ZoneOffset.UTC);
}
private AuthSessionEntity requireActiveSession(String sessionToken) {
AuthSessionEntity session = authSessionRepository.findBySessionToken(sessionToken)
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "session not found"));
if (session.getLogoutAt() != null || session.getExpiresAt() == null || !session.getExpiresAt().isAfter(now())) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "session expired");
}
return session;
}
}
@@ -0,0 +1,158 @@
package com.cisd.tms.modules.auth.service;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.exception.BizException;
import com.cisd.tms.modules.auth.dto.CompatPasswordLoginRequest;
import com.cisd.tms.modules.auth.dto.CompatUkeyLoginRequest;
import com.cisd.tms.modules.auth.dto.LoginRequest;
import com.cisd.tms.modules.auth.dto.LoginResponse;
import com.cisd.tms.modules.auth.dto.UkeyLoginRandomResponse;
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
import com.cisd.tms.modules.auth.enums.RoleCode;
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
import com.cisd.tms.modules.mk.dto.UKeySignDTO;
import com.cisd.tms.modules.mk.dto.UKeySignEntity;
import com.cisd.tms.modules.mk.enums.MasterKeyStatus;
import com.cisd.tms.modules.mk.service.LmkService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
@Service
public class CompatAuthService {
private final AuthService authService;
private final RoleUkeyBindingRepository roleUkeyBindingRepository;
private final LmkService lmkService;
private final UkeyLoginRandomService ukeyLoginRandomService;
private final CompatUkeyVerifier compatUkeyVerifier;
private final ObjectMapper objectMapper;
public CompatAuthService(
AuthService authService,
RoleUkeyBindingRepository roleUkeyBindingRepository,
LmkService lmkService,
UkeyLoginRandomService ukeyLoginRandomService,
CompatUkeyVerifier compatUkeyVerifier,
ObjectMapper objectMapper
) {
this.authService = authService;
this.roleUkeyBindingRepository = roleUkeyBindingRepository;
this.lmkService = lmkService;
this.ukeyLoginRandomService = ukeyLoginRandomService;
this.compatUkeyVerifier = compatUkeyVerifier;
this.objectMapper = objectMapper;
}
public UkeyLoginRandomResponse issueUkeyLoginRandoms(String legacyRole, Integer count) {
RoleCode roleCode = resolveRoleCode(legacyRole);
int resolvedCount = count == null ? roleCode.getRequiredUkeyCount() : count;
UkeyLoginRandomResponse response = new UkeyLoginRandomResponse();
response.setRoleCode(roleCode.getCode());
response.setRandoms(ukeyLoginRandomService.issue(roleCode.getCode(), resolvedCount));
return response;
}
public LoginResponse passwordLogin(CompatPasswordLoginRequest request) {
ensureMasterKeyReady();
RoleCode roleCode = resolveRoleCode(request.getRole());
LoginRequest loginRequest = new LoginRequest();
loginRequest.setRoleCode(roleCode.getCode());
loginRequest.setPassword(request.getPassword());
return authService.login(loginRequest);
}
public LoginResponse ukeyLogin(CompatUkeyLoginRequest request) {
ensureMasterKeyReady();
RoleCode roleCode = resolveRoleCode(request.getRole());
List<RoleUkeyBindingEntity> activeBindings = roleUkeyBindingRepository.findActiveByRoleCode(roleCode.getCode());
validateUkeyCount(roleCode, activeBindings, request.getAuthInfo());
Map<String, RoleUkeyBindingEntity> bindingsByPubKey = activeBindings.stream()
.collect(Collectors.toMap(RoleUkeyBindingEntity::getUkeyPubkey, item -> item, (left, right) -> left, LinkedHashMap::new));
Set<String> requestPubKeys = request.getAuthInfo().stream()
.map(CompatUkeyLoginRequest.LoginAuthInfo::getPubKey)
.collect(Collectors.toSet());
if (requestPubKeys.size() != request.getAuthInfo().size() || !bindingsByPubKey.keySet().containsAll(requestPubKeys)) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey auth info does not match bound role");
}
ukeyLoginRandomService.assertIssued(
roleCode.getCode(),
request.getAuthInfo().stream().map(CompatUkeyLoginRequest.LoginAuthInfo::getRb).toList()
);
String authKeyPair = lmkService.exportIkPublicKeyHex();
List<String> matchedSerials = new ArrayList<>();
for (CompatUkeyLoginRequest.LoginAuthInfo loginAuthInfo : request.getAuthInfo()) {
RoleUkeyBindingEntity binding = bindingsByPubKey.get(loginAuthInfo.getPubKey());
compatUkeyVerifier.verifyIssuedBinding(buildIssuePayload(request.getRole(), loginAuthInfo, authKeyPair), loginAuthInfo.getIssueSign());
compatUkeyVerifier.verifyLoginSignature(loginAuthInfo.getPubKey(), loginAuthInfo.getLoginSignData(), loginAuthInfo.getLoginSign());
matchedSerials.add(binding.getUkeySerial());
}
LoginRequest loginRequest = new LoginRequest();
loginRequest.setRoleCode(roleCode.getCode());
loginRequest.setPassword(request.getPassword());
loginRequest.setUkeySerials(matchedSerials);
return authService.login(loginRequest);
}
private void ensureMasterKeyReady() {
MasterKeyStatus.StatusDetail status = lmkService.getMasterKeyStatus();
if (status == null || status.getCode() == MasterKeyStatus.ABNORMAL.getCode()) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "master key is not ready");
}
}
private void validateUkeyCount(
RoleCode roleCode,
List<RoleUkeyBindingEntity> activeBindings,
List<CompatUkeyLoginRequest.LoginAuthInfo> authInfos
) {
if (authInfos == null || authInfos.size() != roleCode.getRequiredUkeyCount()) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey count does not satisfy role requirement");
}
if (activeBindings.size() != roleCode.getRequiredUkeyCount()) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey count does not satisfy role requirement");
}
}
private String buildIssuePayload(String legacyRole, CompatUkeyLoginRequest.LoginAuthInfo loginAuthInfo, String authKeyPair) {
UKeySignDTO uKeySignDTO = new UKeySignDTO();
uKeySignDTO.setPubKey(loginAuthInfo.getPubKey());
uKeySignDTO.setRole(normalizeLegacyRole(legacyRole));
uKeySignDTO.setUid(loginAuthInfo.getUid());
uKeySignDTO.setRid(loginAuthInfo.getRid());
try {
return objectMapper.writeValueAsString(UKeySignEntity.getInstance(uKeySignDTO, authKeyPair));
} catch (JsonProcessingException ex) {
throw new IllegalStateException("serialize ukey issue payload failed", ex);
}
}
private RoleCode resolveRoleCode(String role) {
return switch (normalizeLegacyRole(role)) {
case "superadmin" -> RoleCode.SUPER_ADMIN;
case "keyadmin" -> RoleCode.KEY_ADMIN;
case "auditadmin" -> RoleCode.AUDIT_ADMIN;
case "configadmin", "opsadmin" -> RoleCode.OPS_ADMIN;
case "super_admin" -> RoleCode.SUPER_ADMIN;
case "key_admin" -> RoleCode.KEY_ADMIN;
case "audit_admin" -> RoleCode.AUDIT_ADMIN;
case "ops_admin" -> RoleCode.OPS_ADMIN;
default -> throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "invalid role");
};
}
private String normalizeLegacyRole(String role) {
return role == null ? "" : role.trim().toLowerCase(Locale.ROOT);
}
}
@@ -0,0 +1,8 @@
package com.cisd.tms.modules.auth.service;
public interface CompatUkeyVerifier {
void verifyIssuedBinding(String payload, String issueSign);
void verifyLoginSignature(String pubKey, String loginSignData, String loginSign);
}
@@ -0,0 +1,63 @@
package com.cisd.tms.modules.auth.service;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.exception.BizException;
import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class InMemoryUkeyLoginRandomService implements UkeyLoginRandomService {
private static final int RANDOM_BYTES = 16;
private static final int EXPIRE_MINUTES = 10;
private final PcieCryptoService pcieCryptoService;
private final Clock clock;
private final Map<String, IssuedRandoms> store = new ConcurrentHashMap<>();
@Autowired
public InMemoryUkeyLoginRandomService(PcieCryptoService pcieCryptoService) {
this(pcieCryptoService, Clock.systemUTC());
}
InMemoryUkeyLoginRandomService(PcieCryptoService pcieCryptoService, Clock clock) {
this.pcieCryptoService = pcieCryptoService;
this.clock = clock;
}
@Override
public List<String> issue(String roleCode, int count) {
if (count <= 0) {
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "count must be positive");
}
List<String> randoms = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
randoms.add(Hex.toHexString(pcieCryptoService.generateRandom(RANDOM_BYTES)));
}
store.put(roleCode, new IssuedRandoms(randoms, clock.instant().plus(EXPIRE_MINUTES, ChronoUnit.MINUTES)));
return randoms;
}
@Override
public void assertIssued(String roleCode, List<String> randoms) {
IssuedRandoms issuedRandoms = store.remove(roleCode);
if (issuedRandoms == null || issuedRandoms.expiresAt().isBefore(clock.instant())) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "login randoms are missing or expired");
}
if (randoms == null || randoms.size() != issuedRandoms.randoms().size() || !issuedRandoms.randoms().containsAll(randoms)) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "login random verification failed");
}
}
private record IssuedRandoms(List<String> randoms, Instant expiresAt) {
}
}
@@ -0,0 +1,8 @@
package com.cisd.tms.modules.auth.service;
public interface PasswordHasher {
String hash(String password, String salt);
boolean matches(String rawPassword, String salt, String expectedHash);
}
@@ -0,0 +1,34 @@
package com.cisd.tms.modules.auth.service;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Base64;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import org.springframework.stereotype.Component;
@Component
public class Pbkdf2PasswordHasher implements PasswordHasher {
private static final int ITERATIONS = 65_536;
private static final int KEY_LENGTH = 256;
@Override
public String hash(String password, String salt) {
try {
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(StandardCharsets.UTF_8), ITERATIONS, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
return Base64.getEncoder().encodeToString(keyFactory.generateSecret(spec).getEncoded());
} catch (GeneralSecurityException ex) {
throw new IllegalStateException("failed to hash password", ex);
}
}
@Override
public boolean matches(String rawPassword, String salt, String expectedHash) {
byte[] actual = hash(rawPassword, salt).getBytes(StandardCharsets.UTF_8);
byte[] expected = expectedHash.getBytes(StandardCharsets.UTF_8);
return MessageDigest.isEqual(actual, expected);
}
}
@@ -0,0 +1,66 @@
package com.cisd.tms.modules.auth.service;
import com.cisd.tms.common.enums.ErrorCode;
import com.cisd.tms.common.exception.BizException;
import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds;
import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest;
import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService;
import com.cisd.tms.modules.mk.service.LmkService;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.stereotype.Component;
@Component
public class PcieCompatUkeyVerifier implements CompatUkeyVerifier {
private final LmkService lmkService;
private final PcieCryptoService pcieCryptoService;
public PcieCompatUkeyVerifier(LmkService lmkService, PcieCryptoService pcieCryptoService) {
this.lmkService = lmkService;
this.pcieCryptoService = pcieCryptoService;
}
@Override
public void verifyIssuedBinding(String payload, String issueSign) {
try {
lmkService.verifyIk(payload, issueSign);
} catch (BizException ex) {
throw ex;
} catch (RuntimeException ex) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "issue signature verification failed");
}
}
@Override
public void verifyLoginSignature(String pubKey, String loginSignData, String loginSign) {
EccExternalVerifyRequest request = new EccExternalVerifyRequest();
request.setAlgId(Gm0018AlgorithmIds.SM2_SIGN);
request.setPublicKeyBlob(decodeBlob(pubKey, "login public key is invalid"));
request.setData(loginSignData.getBytes(StandardCharsets.UTF_8));
request.setSignature(decodeBlob(loginSign, "login signature is invalid"));
try {
pcieCryptoService.eccExternalVerify(request);
} catch (BizException ex) {
throw ex;
} catch (RuntimeException ex) {
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "login signature verification failed");
}
}
private byte[] decodeBlob(String value, String message) {
String normalized = value == null ? "" : value.trim();
if (normalized.isEmpty()) {
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), message);
}
if (normalized.matches("(?i)^[0-9a-f]+$") && normalized.length() % 2 == 0) {
return Hex.decode(normalized);
}
try {
return Base64.getDecoder().decode(normalized);
} catch (IllegalArgumentException ex) {
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), message);
}
}
}
@@ -0,0 +1,10 @@
package com.cisd.tms.modules.auth.service;
import java.util.List;
public interface UkeyLoginRandomService {
List<String> issue(String roleCode, int count);
void assertIssued(String roleCode, List<String> randoms);
}
@@ -0,0 +1,53 @@
package com.cisd.tms.modules.device.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "tms.device.profile")
public class DeviceProfileProperties {
private String model = "SYD7108";
private String name = "跨境支付终端一体机";
private String cpuModelDefault = "";
private String memoryTotalDefault = "16GB";
private String diskTotalDefault = "256G";
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCpuModelDefault() {
return cpuModelDefault;
}
public void setCpuModelDefault(String cpuModelDefault) {
this.cpuModelDefault = cpuModelDefault;
}
public String getMemoryTotalDefault() {
return memoryTotalDefault;
}
public void setMemoryTotalDefault(String memoryTotalDefault) {
this.memoryTotalDefault = memoryTotalDefault;
}
public String getDiskTotalDefault() {
return diskTotalDefault;
}
public void setDiskTotalDefault(String diskTotalDefault) {
this.diskTotalDefault = diskTotalDefault;
}
}
File diff suppressed because it is too large Load Diff
@@ -8,12 +8,13 @@ import com.cisd.tms.modules.device.dto.DeviceRuntimeStatusResponse;
import com.cisd.tms.modules.device.service.DeviceProfileService;
import com.cisd.tms.modules.device.service.DeviceRuntimeStatusService;
import com.cisd.tms.modules.device.service.DeviceService;
import com.cisd.tms.security.internal.InternalApiAuthInterceptor;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -62,10 +63,8 @@ public class DeviceController {
@PostMapping("/restart")
@Operation(summary = "重启设备服务", description = "受理设备重启请求,并记录触发操作的内部用户。")
public ApiResponse<DeviceActionResponse> restart(
@Parameter(description = "触发重启的操作人,来自内部鉴权链路透传的 X-User 请求头")
@RequestHeader(value = "X-User", required = false) String operator
) {
public ApiResponse<DeviceActionResponse> restart(HttpServletRequest request) {
String operator = (String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE);
return ApiResponse.success(deviceService.restart(operator));
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "加密卡运行状态")
public class CryptoCardRuntimeStatus {
@Schema(description = "状态", example = "NORMAL")
private String status;
@Schema(description = "状态说明", example = "就绪状态")
private String message;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@@ -0,0 +1,48 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "设备基础信息")
public class DeviceProfileDeviceSection {
@Schema(description = "设备型号", example = "SYD7108")
private String model;
@Schema(description = "设备名称", example = "跨境支付终端一体机")
private String name;
@Schema(description = "设备序列号", example = "1234567890ABCDEF")
private String serialNumber;
@Schema(description = "设备版本", example = "V1.00")
private String deviceVersion;
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public String getDeviceVersion() {
return deviceVersion;
}
public void setDeviceVersion(String deviceVersion) {
this.deviceVersion = deviceVersion;
}
}
@@ -0,0 +1,48 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "设备硬件信息")
public class DeviceProfileHardwareSection {
@Schema(description = "密码卡名称", example = "SYD1408加密卡")
private String cryptoCardName;
@Schema(description = "CPU 型号", example = "Hygon C86-3G (OPN:3350)")
private String cpuModel;
@Schema(description = "内存总量", example = "32GB")
private String memoryTotal;
@Schema(description = "磁盘总量", example = "953.87GB")
private String diskTotal;
public String getCryptoCardName() {
return cryptoCardName;
}
public void setCryptoCardName(String cryptoCardName) {
this.cryptoCardName = cryptoCardName;
}
public String getCpuModel() {
return cpuModel;
}
public void setCpuModel(String cpuModel) {
this.cpuModel = cpuModel;
}
public String getMemoryTotal() {
return memoryTotal;
}
public void setMemoryTotal(String memoryTotal) {
this.memoryTotal = memoryTotal;
}
public String getDiskTotal() {
return diskTotal;
}
public void setDiskTotal(String diskTotal) {
this.diskTotal = diskTotal;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "设备画像响应")
public class DeviceProfileResponse {
@Schema(description = "设备基础信息")
private DeviceProfileDeviceSection device;
@Schema(description = "设备硬件信息")
private DeviceProfileHardwareSection hardware;
@Schema(description = "软件版本信息")
private List<DeviceProfileSoftwareItem> software = new ArrayList<>();
public DeviceProfileDeviceSection getDevice() {
return device;
}
public void setDevice(DeviceProfileDeviceSection device) {
this.device = device;
}
public DeviceProfileHardwareSection getHardware() {
return hardware;
}
public void setHardware(DeviceProfileHardwareSection hardware) {
this.hardware = hardware;
}
public List<DeviceProfileSoftwareItem> getSoftware() {
return software;
}
public void setSoftware(List<DeviceProfileSoftwareItem> software) {
this.software = software;
}
}
@@ -0,0 +1,38 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "软件组件信息")
public class DeviceProfileSoftwareItem {
@Schema(description = "组件编码", example = "RABBITMQ")
private String componentCode;
@Schema(description = "组件名称", example = "RabbitMQ")
private String componentName;
@Schema(description = "组件版本", example = "RabbitMQ V3.8.21")
private String version;
public String getComponentCode() {
return componentCode;
}
public void setComponentCode(String componentCode) {
this.componentCode = componentCode;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
@@ -0,0 +1,42 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "设备运行状态响应")
public class DeviceRuntimeStatusResponse {
@Schema(description = "硬件运行状态")
private HardwareRuntimeStatusSection hardware;
@Schema(description = "软件运行状态")
private List<SoftwareRuntimeStatusItem> software = new ArrayList<>();
@Schema(description = "采集时间", example = "2026-03-13T14:30:00+08:00")
private String collectedAt;
public HardwareRuntimeStatusSection getHardware() {
return hardware;
}
public void setHardware(HardwareRuntimeStatusSection hardware) {
this.hardware = hardware;
}
public List<SoftwareRuntimeStatusItem> getSoftware() {
return software;
}
public void setSoftware(List<SoftwareRuntimeStatusItem> software) {
this.software = software;
}
public String getCollectedAt() {
return collectedAt;
}
public void setCollectedAt(String collectedAt) {
this.collectedAt = collectedAt;
}
}
@@ -0,0 +1,51 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "硬件运行状态")
public class HardwareRuntimeStatusSection {
@Schema(description = "CPU 运行状态")
private UsageMetricStatus cpu;
@Schema(description = "内存运行状态")
private UsageMetricStatus memory;
@Schema(description = "磁盘运行状态")
private UsageMetricStatus disk;
@Schema(description = "加密卡运行状态")
private CryptoCardRuntimeStatus cryptoCard;
public UsageMetricStatus getCpu() {
return cpu;
}
public void setCpu(UsageMetricStatus cpu) {
this.cpu = cpu;
}
public UsageMetricStatus getMemory() {
return memory;
}
public void setMemory(UsageMetricStatus memory) {
this.memory = memory;
}
public UsageMetricStatus getDisk() {
return disk;
}
public void setDisk(UsageMetricStatus disk) {
this.disk = disk;
}
public CryptoCardRuntimeStatus getCryptoCard() {
return cryptoCard;
}
public void setCryptoCard(CryptoCardRuntimeStatus cryptoCard) {
this.cryptoCard = cryptoCard;
}
}
@@ -0,0 +1,62 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "软件运行状态项")
public class SoftwareRuntimeStatusItem {
@Schema(description = "组件编码", example = "RABBITMQ")
private String componentCode;
@Schema(description = "组件名称", example = "消息队列")
private String componentName;
@Schema(description = "展示名称", example = "RabbitMQ V3.8.21")
private String displayName;
@Schema(description = "状态", example = "NORMAL")
private String status;
@Schema(description = "状态说明", example = "正常")
private String message;
public String getComponentCode() {
return componentCode;
}
public void setComponentCode(String componentCode) {
this.componentCode = componentCode;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@@ -0,0 +1,62 @@
package com.cisd.tms.modules.device.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "资源使用量状态")
public class UsageMetricStatus {
@Schema(description = "已使用容量(GB)", example = "23.55")
private Double usedGb;
@Schema(description = "总容量(GB)", example = "32.0")
private Double totalGb;
@Schema(description = "使用率百分比", example = "73.59")
private Double usagePercent;
@Schema(description = "状态", example = "NORMAL")
private String status;
@Schema(description = "状态说明", example = "正常")
private String message;
public Double getUsedGb() {
return usedGb;
}
public void setUsedGb(Double usedGb) {
this.usedGb = usedGb;
}
public Double getTotalGb() {
return totalGb;
}
public void setTotalGb(Double totalGb) {
this.totalGb = totalGb;
}
public Double getUsagePercent() {
return usagePercent;
}
public void setUsagePercent(Double usagePercent) {
this.usagePercent = usagePercent;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@@ -0,0 +1,39 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoBackupUserKeyInternalRequest {
@Min(0)
private int keyIndex;
@Min(0)
private int keyType;
@Min(1)
private int outBufferSize;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoChangePrivateKeyPasswordInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String oldPasswordBase64;
@NotBlank
private String newPasswordBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getOldPasswordBase64() {
return oldPasswordBase64;
}
public void setOldPasswordBase64(String oldPasswordBase64) {
this.oldPasswordBase64 = oldPasswordBase64;
}
public String getNewPasswordBase64() {
return newPasswordBase64;
}
public void setNewPasswordBase64(String newPasswordBase64) {
this.newPasswordBase64 = newPasswordBase64;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoDigestInternalRequest {
@Min(1)
private int algId;
@NotBlank
private String dataBase64;
@Min(1)
private int outBufferSize = 64;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,62 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoExchangeEnvelopeEccInternalRequest {
@Min(0)
private int keyIndex;
@Min(1)
private int algId;
@NotBlank
private String publicKeyBase64;
@NotBlank
private String inputEnvelopeBase64;
@Min(1)
private int outBufferSize;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public String getPublicKeyBase64() {
return publicKeyBase64;
}
public void setPublicKeyBase64(String publicKeyBase64) {
this.publicKeyBase64 = publicKeyBase64;
}
public String getInputEnvelopeBase64() {
return inputEnvelopeBase64;
}
public void setInputEnvelopeBase64(String inputEnvelopeBase64) {
this.inputEnvelopeBase64 = inputEnvelopeBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,51 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoExchangeEnvelopeRsaInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String publicKeyBase64;
@NotBlank
private String inputEnvelopeBase64;
@Min(1)
private int outBufferSize;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getPublicKeyBase64() {
return publicKeyBase64;
}
public void setPublicKeyBase64(String publicKeyBase64) {
this.publicKeyBase64 = publicKeyBase64;
}
public String getInputEnvelopeBase64() {
return inputEnvelopeBase64;
}
public void setInputEnvelopeBase64(String inputEnvelopeBase64) {
this.inputEnvelopeBase64 = inputEnvelopeBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoFileCreateInternalRequest {
@NotBlank
private String fileName;
@Min(1)
private int fileSize;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getFileSize() {
return fileSize;
}
public void setFileSize(int fileSize) {
this.fileSize = fileSize;
}
}
@@ -0,0 +1,17 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.NotBlank;
public class CryptoFileDeleteInternalRequest {
@NotBlank
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoFileReadInternalRequest {
@NotBlank
private String fileName;
@Min(0)
private int offset;
@Min(1)
private int readLength;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getReadLength() {
return readLength;
}
public void setReadLength(int readLength) {
this.readLength = readLength;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoFileWriteInternalRequest {
@NotBlank
private String fileName;
@Min(0)
private int offset;
@NotBlank
private String dataBase64;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
}
@@ -0,0 +1,95 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoGenerateAgreementDataAndKeyEccInternalRequest {
@Min(0)
private int iskIndex;
@Min(1)
private int keyBits;
@NotBlank
private String responseIdBase64;
@NotBlank
private String sponsorIdBase64;
@NotBlank
private String sponsorPublicKeyBase64;
@NotBlank
private String sponsorTmpPublicKeyBase64;
@Min(1)
private int responsePublicKeyBufferSize;
@Min(1)
private int responseTmpPublicKeyBufferSize;
public int getIskIndex() {
return iskIndex;
}
public void setIskIndex(int iskIndex) {
this.iskIndex = iskIndex;
}
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public String getResponseIdBase64() {
return responseIdBase64;
}
public void setResponseIdBase64(String responseIdBase64) {
this.responseIdBase64 = responseIdBase64;
}
public String getSponsorIdBase64() {
return sponsorIdBase64;
}
public void setSponsorIdBase64(String sponsorIdBase64) {
this.sponsorIdBase64 = sponsorIdBase64;
}
public String getSponsorPublicKeyBase64() {
return sponsorPublicKeyBase64;
}
public void setSponsorPublicKeyBase64(String sponsorPublicKeyBase64) {
this.sponsorPublicKeyBase64 = sponsorPublicKeyBase64;
}
public String getSponsorTmpPublicKeyBase64() {
return sponsorTmpPublicKeyBase64;
}
public void setSponsorTmpPublicKeyBase64(String sponsorTmpPublicKeyBase64) {
this.sponsorTmpPublicKeyBase64 = sponsorTmpPublicKeyBase64;
}
public int getResponsePublicKeyBufferSize() {
return responsePublicKeyBufferSize;
}
public void setResponsePublicKeyBufferSize(int responsePublicKeyBufferSize) {
this.responsePublicKeyBufferSize = responsePublicKeyBufferSize;
}
public int getResponseTmpPublicKeyBufferSize() {
return responseTmpPublicKeyBufferSize;
}
public void setResponseTmpPublicKeyBufferSize(int responseTmpPublicKeyBufferSize) {
this.responseTmpPublicKeyBufferSize = responseTmpPublicKeyBufferSize;
}
}
@@ -0,0 +1,28 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoGenerateKekInternalRequest {
@Min(1)
private int keyBits;
@Min(0)
private int keyIndex;
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
}
@@ -0,0 +1,39 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoGenerateKeyPairInternalRequest {
@Min(1)
private int keyBits;
@Min(0)
private int keyIndex;
@Min(0)
private int keyType;
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
}
@@ -0,0 +1,106 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoGenerateSessionKeyEccInternalRequest {
@Min(0)
private int iskIndex;
@Min(1)
private int keyBits;
@NotBlank
private String sponsorIdBase64;
@NotBlank
private String responseIdBase64;
@NotBlank
private String responsePublicKeyBase64;
@NotBlank
private String responseTmpPublicKeyBase64;
@Min(1)
private int sponsorPublicKeyBufferSize;
@Min(1)
private int sponsorTmpPublicKeyBufferSize;
@Min(1)
private int sessionKeyBufferSize;
public int getIskIndex() {
return iskIndex;
}
public void setIskIndex(int iskIndex) {
this.iskIndex = iskIndex;
}
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public String getSponsorIdBase64() {
return sponsorIdBase64;
}
public void setSponsorIdBase64(String sponsorIdBase64) {
this.sponsorIdBase64 = sponsorIdBase64;
}
public String getResponseIdBase64() {
return responseIdBase64;
}
public void setResponseIdBase64(String responseIdBase64) {
this.responseIdBase64 = responseIdBase64;
}
public String getResponsePublicKeyBase64() {
return responsePublicKeyBase64;
}
public void setResponsePublicKeyBase64(String responsePublicKeyBase64) {
this.responsePublicKeyBase64 = responsePublicKeyBase64;
}
public String getResponseTmpPublicKeyBase64() {
return responseTmpPublicKeyBase64;
}
public void setResponseTmpPublicKeyBase64(String responseTmpPublicKeyBase64) {
this.responseTmpPublicKeyBase64 = responseTmpPublicKeyBase64;
}
public int getSponsorPublicKeyBufferSize() {
return sponsorPublicKeyBufferSize;
}
public void setSponsorPublicKeyBufferSize(int sponsorPublicKeyBufferSize) {
this.sponsorPublicKeyBufferSize = sponsorPublicKeyBufferSize;
}
public int getSponsorTmpPublicKeyBufferSize() {
return sponsorTmpPublicKeyBufferSize;
}
public void setSponsorTmpPublicKeyBufferSize(int sponsorTmpPublicKeyBufferSize) {
this.sponsorTmpPublicKeyBufferSize = sponsorTmpPublicKeyBufferSize;
}
public int getSessionKeyBufferSize() {
return sessionKeyBufferSize;
}
public void setSessionKeyBufferSize(int sessionKeyBufferSize) {
this.sessionKeyBufferSize = sessionKeyBufferSize;
}
}
@@ -0,0 +1,50 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoGenerateStandardEccKeyPairInternalRequest {
@Min(1)
private int algId;
@Min(1)
private int keyBits;
@Min(1)
private int publicKeyBufferSize;
@Min(1)
private int privateKeyBufferSize;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public int getPublicKeyBufferSize() {
return publicKeyBufferSize;
}
public void setPublicKeyBufferSize(int publicKeyBufferSize) {
this.publicKeyBufferSize = publicKeyBufferSize;
}
public int getPrivateKeyBufferSize() {
return privateKeyBufferSize;
}
public void setPrivateKeyBufferSize(int privateKeyBufferSize) {
this.privateKeyBufferSize = privateKeyBufferSize;
}
}
@@ -0,0 +1,39 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoGenerateStandardRsaKeyPairInternalRequest {
@Min(1)
private int keyBits;
@Min(1)
private int publicKeyBufferSize;
@Min(1)
private int privateKeyBufferSize;
public int getKeyBits() {
return keyBits;
}
public void setKeyBits(int keyBits) {
this.keyBits = keyBits;
}
public int getPublicKeyBufferSize() {
return publicKeyBufferSize;
}
public void setPublicKeyBufferSize(int publicKeyBufferSize) {
this.publicKeyBufferSize = publicKeyBufferSize;
}
public int getPrivateKeyBufferSize() {
return privateKeyBufferSize;
}
public void setPrivateKeyBufferSize(int privateKeyBufferSize) {
this.privateKeyBufferSize = privateKeyBufferSize;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoHmacInternalRequest {
@Min(1)
private int algId;
@NotBlank
private String keyBase64;
@NotBlank
private String dataBase64;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public String getKeyBase64() {
return keyBase64;
}
public void setKeyBase64(String keyBase64) {
this.keyBase64 = keyBase64;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoImportEncryptedKeyPairEccInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String envelopedKeyBlobBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getEnvelopedKeyBlobBase64() {
return envelopedKeyBlobBase64;
}
public void setEnvelopedKeyBlobBase64(String envelopedKeyBlobBase64) {
this.envelopedKeyBlobBase64 = envelopedKeyBlobBase64;
}
}
@@ -0,0 +1,51 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoImportEncryptedKeyPairRsaInternalRequest {
@Min(0)
private int keyIndex;
@Min(1)
private int symAlgId;
@NotBlank
private String wrappedKeyBase64;
@NotBlank
private String encryptedDataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getSymAlgId() {
return symAlgId;
}
public void setSymAlgId(int symAlgId) {
this.symAlgId = symAlgId;
}
public String getWrappedKeyBase64() {
return wrappedKeyBase64;
}
public void setWrappedKeyBase64(String wrappedKeyBase64) {
this.wrappedKeyBase64 = wrappedKeyBase64;
}
public String getEncryptedDataBase64() {
return encryptedDataBase64;
}
public void setEncryptedDataBase64(String encryptedDataBase64) {
this.encryptedDataBase64 = encryptedDataBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoImportKekInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String keyDataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getKeyDataBase64() {
return keyDataBase64;
}
public void setKeyDataBase64(String keyDataBase64) {
this.keyDataBase64 = keyDataBase64;
}
}
@@ -0,0 +1,51 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoImportKeyPairInternalRequest {
@Min(0)
private int keyIndex;
@Min(0)
private int keyType;
@NotBlank
private String publicKeyBase64;
@NotBlank
private String privateKeyBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
public String getPublicKeyBase64() {
return publicKeyBase64;
}
public void setPublicKeyBase64(String publicKeyBase64) {
this.publicKeyBase64 = publicKeyBase64;
}
public String getPrivateKeyBase64() {
return privateKeyBase64;
}
public void setPrivateKeyBase64(String privateKeyBase64) {
this.privateKeyBase64 = privateKeyBase64;
}
}
@@ -0,0 +1,28 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.NotBlank;
public class CryptoInitIdentifyInternalRequest {
@NotBlank
private String oldPinBase64;
@NotBlank
private String newPinBase64;
public String getOldPinBase64() {
return oldPinBase64;
}
public void setOldPinBase64(String oldPinBase64) {
this.oldPinBase64 = oldPinBase64;
}
public String getNewPinBase64() {
return newPinBase64;
}
public void setNewPinBase64(String newPinBase64) {
this.newPinBase64 = newPinBase64;
}
}
@@ -0,0 +1,39 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
public class CryptoKekComponentExportInternalRequest {
@Min(0)
private int keyIndex;
@Min(0)
private int componentNum;
@Min(1)
private int componentSize;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getComponentNum() {
return componentNum;
}
public void setComponentNum(int componentNum) {
this.componentNum = componentNum;
}
public int getComponentSize() {
return componentSize;
}
public void setComponentSize(int componentSize) {
this.componentSize = componentSize;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoKekComponentImportInternalRequest {
@Min(0)
private int keyIndex;
@Min(0)
private int componentNum;
@NotBlank
private String componentDataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getComponentNum() {
return componentNum;
}
public void setComponentNum(int componentNum) {
this.componentNum = componentNum;
}
public String getComponentDataBase64() {
return componentDataBase64;
}
public void setComponentDataBase64(String componentDataBase64) {
this.componentDataBase64 = componentDataBase64;
}
}
@@ -0,0 +1,61 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoMacInternalRequest {
@Min(1)
private int algId;
@NotBlank
private String keyBase64;
private String ivBase64;
@NotBlank
private String dataBase64;
@Min(1)
private int outBufferSize = 32;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public String getKeyBase64() {
return keyBase64;
}
public void setKeyBase64(String keyBase64) {
this.keyBase64 = keyBase64;
}
public String getIvBase64() {
return ivBase64;
}
public void setIvBase64(String ivBase64) {
this.ivBase64 = ivBase64;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoPrivateKeyAccessInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String passwordBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getPasswordBase64() {
return passwordBase64;
}
public void setPasswordBase64(String passwordBase64) {
this.passwordBase64 = passwordBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoReadUkeyIkComponentInternalRequest {
@Min(0)
private int keyType;
@NotBlank
private String ukeyPinBase64;
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
public String getUkeyPinBase64() {
return ukeyPinBase64;
}
public void setUkeyPinBase64(String ukeyPinBase64) {
this.ukeyPinBase64 = ukeyPinBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoRecoverKekInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String encryptedKeyBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getEncryptedKeyBase64() {
return encryptedKeyBase64;
}
public void setEncryptedKeyBase64(String encryptedKeyBase64) {
this.encryptedKeyBase64 = encryptedKeyBase64;
}
}
@@ -0,0 +1,34 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import java.util.Map;
public class CryptoRecoverLmkExInternalRequest {
private String componentBase64;
private String lmkMacHex;
private Map<String, String> components;
public String getComponentBase64() {
return componentBase64;
}
public void setComponentBase64(String componentBase64) {
this.componentBase64 = componentBase64;
}
public String getLmkMacHex() {
return lmkMacHex;
}
public void setLmkMacHex(String lmkMacHex) {
this.lmkMacHex = lmkMacHex;
}
public Map<String, String> getComponents() {
return components;
}
public void setComponents(Map<String, String> components) {
this.components = components;
}
}
@@ -0,0 +1,51 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoRecoverUserKeyInternalRequest {
@Min(0)
private int keyIndex;
@Min(0)
private int keyType;
@NotBlank
private String encryptedKeyBase64;
@Min(0)
private int storeFlag = 1;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public int getKeyType() {
return keyType;
}
public void setKeyType(int keyType) {
this.keyType = keyType;
}
public String getEncryptedKeyBase64() {
return encryptedKeyBase64;
}
public void setEncryptedKeyBase64(String encryptedKeyBase64) {
this.encryptedKeyBase64 = encryptedKeyBase64;
}
public int getStoreFlag() {
return storeFlag;
}
public void setStoreFlag(int storeFlag) {
this.storeFlag = storeFlag;
}
}
@@ -0,0 +1,17 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.NotBlank;
public class CryptoRestoreAllKeysInternalRequest {
@NotBlank
private String keyImageBase64;
public String getKeyImageBase64() {
return keyImageBase64;
}
public void setKeyImageBase64(String keyImageBase64) {
this.keyImageBase64 = keyImageBase64;
}
}
@@ -0,0 +1,61 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoSymmetricInternalRequest {
@Min(1)
private int algId;
@NotBlank
private String keyBase64;
private String ivBase64;
@NotBlank
private String dataBase64;
@Min(1)
private int outBufferSize;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public String getKeyBase64() {
return keyBase64;
}
public void setKeyBase64(String keyBase64) {
this.keyBase64 = keyBase64;
}
public String getIvBase64() {
return ivBase64;
}
public void setIvBase64(String ivBase64) {
this.ivBase64 = ivBase64;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,72 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoSymmetricKekInternalRequest {
@Min(1)
private int algId;
@Min(0)
private int kekIndex;
@NotBlank
private String wrappedKeyBase64;
private String ivBase64;
@NotBlank
private String dataBase64;
@Min(1)
private int outBufferSize;
public int getAlgId() {
return algId;
}
public void setAlgId(int algId) {
this.algId = algId;
}
public int getKekIndex() {
return kekIndex;
}
public void setKekIndex(int kekIndex) {
this.kekIndex = kekIndex;
}
public String getWrappedKeyBase64() {
return wrappedKeyBase64;
}
public void setWrappedKeyBase64(String wrappedKeyBase64) {
this.wrappedKeyBase64 = wrappedKeyBase64;
}
public String getIvBase64() {
return ivBase64;
}
public void setIvBase64(String ivBase64) {
this.ivBase64 = ivBase64;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
public int getOutBufferSize() {
return outBufferSize;
}
public void setOutBufferSize(int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUkeyGenerateInternalRequest {
@Min(0)
private int adminIndex;
@NotBlank
private String ukeyPinBase64;
@NotBlank
private String loginPinBase64;
public int getAdminIndex() {
return adminIndex;
}
public void setAdminIndex(int adminIndex) {
this.adminIndex = adminIndex;
}
public String getUkeyPinBase64() {
return ukeyPinBase64;
}
public void setUkeyPinBase64(String ukeyPinBase64) {
this.ukeyPinBase64 = ukeyPinBase64;
}
public String getLoginPinBase64() {
return loginPinBase64;
}
public void setLoginPinBase64(String loginPinBase64) {
this.loginPinBase64 = loginPinBase64;
}
}
@@ -0,0 +1,28 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.NotBlank;
public class CryptoUkeyLoginInternalRequest {
@NotBlank
private String ukeyPinBase64;
@NotBlank
private String loginPinBase64;
public String getUkeyPinBase64() {
return ukeyPinBase64;
}
public void setUkeyPinBase64(String ukeyPinBase64) {
this.ukeyPinBase64 = ukeyPinBase64;
}
public String getLoginPinBase64() {
return loginPinBase64;
}
public void setLoginPinBase64(String loginPinBase64) {
this.loginPinBase64 = loginPinBase64;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUkeyPinChangeInternalRequest {
@Min(0)
private int pinType;
@NotBlank
private String oldPinBase64;
@NotBlank
private String newPinBase64;
public int getPinType() {
return pinType;
}
public void setPinType(int pinType) {
this.pinType = pinType;
}
public String getOldPinBase64() {
return oldPinBase64;
}
public void setOldPinBase64(String oldPinBase64) {
this.oldPinBase64 = oldPinBase64;
}
public String getNewPinBase64() {
return newPinBase64;
}
public void setNewPinBase64(String newPinBase64) {
this.newPinBase64 = newPinBase64;
}
}
@@ -0,0 +1,17 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.NotBlank;
public class CryptoUkeyPinInternalRequest {
@NotBlank
private String ukeyPinBase64;
public String getUkeyPinBase64() {
return ukeyPinBase64;
}
public void setUkeyPinBase64(String ukeyPinBase64) {
this.ukeyPinBase64 = ukeyPinBase64;
}
}

Some files were not shown because too many files have changed in this diff Show More