feat:升级功能、密码卡框架、主密钥接口
This commit is contained in:
@@ -51,7 +51,7 @@ chmod +x /home/tms/scripts/tms.sh
|
|||||||
说明:
|
说明:
|
||||||
- 脚本默认 `APP_HOME=/home/tms`,并通过 `--spring.config.additional-location=optional:file:<app_home>/config/` 从 `/home/tms/config/` 读取外部配置。
|
- 脚本默认 `APP_HOME=/home/tms`,并通过 `--spring.config.additional-location=optional:file:<app_home>/config/` 从 `/home/tms/config/` 读取外部配置。
|
||||||
- 默认要求 `/home/tms/config/application.yml` 存在。
|
- 默认要求 `/home/tms/config/application.yml` 存在。
|
||||||
- 默认 profile 为 `prod`;可通过 `SPRING_PROFILES_ACTIVE=dev /home/tms/scripts/tms.sh start` 覆盖。
|
- 脚本不再强制指定 profile;默认按 Spring 配置文件自身规则解析,可通过 `SPRING_PROFILES_ACTIVE=dev /home/tms/scripts/tms.sh start` 显式覆盖。
|
||||||
- 可通过 `JAR_PATH=/home/tms/tms-framework.jar` 覆盖 jar 路径。
|
- 可通过 `JAR_PATH=/home/tms/tms-framework.jar` 覆盖 jar 路径。
|
||||||
- 如果部署路径不是 `/home/tms`,使用 `APP_HOME=/your/path /your/path/scripts/tms.sh start`。
|
- 如果部署路径不是 `/home/tms`,使用 `APP_HOME=/your/path /your/path/scripts/tms.sh start`。
|
||||||
- 标准 CISD 初始化辅助脚本位于 `scripts/standard-init/`,部署时需复制到 `/home/tms/bin/`。
|
- 标准 CISD 初始化辅助脚本位于 `scripts/standard-init/`,部署时需复制到 `/home/tms/bin/`。
|
||||||
@@ -75,9 +75,19 @@ Open:
|
|||||||
- Reset create task API: `POST /api/v1/init/reset/tasks`
|
- Reset create task API: `POST /api/v1/init/reset/tasks`
|
||||||
- Reset execute API: `POST /api/v1/init/reset/tasks/{taskId}/execute`
|
- Reset execute API: `POST /api/v1/init/reset/tasks/{taskId}/execute`
|
||||||
- Auth login API: `POST /api/v1/auth/login`
|
- Auth login API: `POST /api/v1/auth/login`
|
||||||
|
- Compat password login API: `POST /api/v1/auth/password-login`
|
||||||
|
- Compat UKey login API: `POST /api/v1/auth/ukey-login`
|
||||||
|
- Compat UKey random API: `GET /api/v1/auth/ukey-login/randoms`
|
||||||
|
- UKey binding issue-sign API: `POST /api/v1/auth/roles/{roleCode}/ukeys/issue-sign`
|
||||||
|
- UKey binding API: `POST /api/v1/auth/roles/{roleCode}/ukeys/bind`
|
||||||
- Device info API: `GET /api/v1/device/info`
|
- Device info API: `GET /api/v1/device/info`
|
||||||
- Device profile API: `GET /api/v1/device/profile`
|
- Device profile API: `GET /api/v1/device/profile`
|
||||||
- Device runtime status API: `GET /api/v1/device/runtime-status`
|
- Device runtime status API: `GET /api/v1/device/runtime-status`
|
||||||
|
- Upgrade package upload API: `POST /api/v1/upgrade-packages`
|
||||||
|
- Upgrade preview API: `POST /api/v1/upgrades/previews`
|
||||||
|
- Upgrade create task API: `POST /api/v1/upgrades`
|
||||||
|
- Upgrade execute API: `POST /api/v1/upgrades/{taskId}/execute`
|
||||||
|
- Upgrade list API: `GET /api/v1/upgrades`
|
||||||
- PCIe crypto count API: `GET /api/v1/device/crypto/device-count`
|
- PCIe crypto count API: `GET /api/v1/device/crypto/device-count`
|
||||||
- PCIe crypto HMAC API: `POST /api/v1/device/crypto/hmac`
|
- PCIe crypto HMAC API: `POST /api/v1/device/crypto/hmac`
|
||||||
|
|
||||||
@@ -139,6 +149,70 @@ Open:
|
|||||||
- `tms.init.executor.rabbitmq-ctl-command` 指向可执行的 `rabbitmqctl`
|
- `tms.init.executor.rabbitmq-ctl-command` 指向可执行的 `rabbitmqctl`
|
||||||
- 运行时 Swagger 文档以 `http://<ip>:8080/swagger-ui.html` 和 `http://<ip>:8080/v3/api-docs/internal-api` 为准
|
- 运行时 Swagger 文档以 `http://<ip>:8080/swagger-ui.html` 和 `http://<ip>:8080/v3/api-docs/internal-api` 为准
|
||||||
|
|
||||||
|
## Offline Upgrade
|
||||||
|
|
||||||
|
最小调用顺序:
|
||||||
|
- `POST /api/v1/upgrade-packages`
|
||||||
|
- `POST /api/v1/upgrades/previews`
|
||||||
|
- `POST /api/v1/upgrades`
|
||||||
|
- `POST /api/v1/upgrades/{taskId}/execute`
|
||||||
|
- `GET /api/v1/upgrades`
|
||||||
|
- `GET /api/v1/upgrades/{taskId}`
|
||||||
|
- `GET /api/v1/upgrades/{taskId}/log`
|
||||||
|
|
||||||
|
当前支持范围:
|
||||||
|
- 仅支持离线升级
|
||||||
|
- 当前支持升级对象:
|
||||||
|
- `TMS`
|
||||||
|
- `STANDARD_APP`
|
||||||
|
- `DIRECT_APP`
|
||||||
|
- 当前不支持:
|
||||||
|
- 在线升级
|
||||||
|
- `CVE` / 操作系统补丁升级
|
||||||
|
- 密码卡固件升级
|
||||||
|
|
||||||
|
当前流程:
|
||||||
|
- 先上传离线升级包,复用现有文件上传能力,得到 `fileId`
|
||||||
|
- 后端基于 `fileId` 解析升级包并做预检
|
||||||
|
- 预检结果返回升级对象、当前版本、目标版本和版本变化提示
|
||||||
|
- 用户确认后创建升级任务
|
||||||
|
- 调用执行接口后,任务异步进入后台执行
|
||||||
|
- 前端通过列表、详情和日志接口轮询任务状态
|
||||||
|
|
||||||
|
当前升级包要求:
|
||||||
|
- 外层为 zip 包
|
||||||
|
- 至少包含:
|
||||||
|
- `manifest.json`
|
||||||
|
- `signature.sig`
|
||||||
|
- `payload.zip`
|
||||||
|
- `signature.sig` 需要能被设备密码卡使用“固件完整性密钥”完成验签
|
||||||
|
- 服务端需要配置 `tms.upgrade.signature-public-key-base64`(Base64 编码的公钥 blob)
|
||||||
|
- `manifest.json` 当前要求包含:
|
||||||
|
- `packageId`
|
||||||
|
- `targetComponent`
|
||||||
|
- `targetVersion`
|
||||||
|
- `minCompatibleVersion`
|
||||||
|
- `description`
|
||||||
|
- `orchestrator`
|
||||||
|
- `fileChecksums.payloadZip`
|
||||||
|
|
||||||
|
当前执行规则:
|
||||||
|
- 同一时刻只允许一个升级任务处于 `RUNNING`
|
||||||
|
- 不允许目标版本低于当前版本
|
||||||
|
- 不满足最小兼容版本时拒绝升级
|
||||||
|
- 升级成功后会更新 `tms_device_software_version`
|
||||||
|
- 升级执行日志统一写入 `tms.upgrade.log-dir`
|
||||||
|
|
||||||
|
当前配置项:
|
||||||
|
- `tms.upgrade.staging-root-dir`
|
||||||
|
- `tms.upgrade.log-dir`
|
||||||
|
- `tms.upgrade.signature-public-key-base64`
|
||||||
|
|
||||||
|
升级包规范见:
|
||||||
|
- [2026-03-19-upgrade-package-spec.md](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-19-upgrade-package-spec.md)
|
||||||
|
- [标准收发器升级包最小样例](/Users/waner/Work/CISD/文档/tms-framework/docs/examples/upgrade-package/standard-app/README.md)
|
||||||
|
- [离线升级包预检联调清单与示例](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-19-upgrade-preview-integration-guide.md)
|
||||||
|
|
||||||
## Architecture (Monolith + Modular)
|
## Architecture (Monolith + Modular)
|
||||||
|
|
||||||
- One deployable Spring Boot application.
|
- One deployable Spring Boot application.
|
||||||
@@ -189,6 +263,13 @@ src/main/java/com/cisd/tms
|
|||||||
│ └── entity
|
│ └── entity
|
||||||
├── init
|
├── init
|
||||||
├── auth
|
├── auth
|
||||||
|
|
||||||
|
## Auth Compat
|
||||||
|
|
||||||
|
当前仓库只包含后端认证接口,不包含登录页前端工程。
|
||||||
|
|
||||||
|
兼容旧管理端的登录调用说明见:
|
||||||
|
- [2026-03-23-auth-compat-integration-guide.md](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-23-auth-compat-integration-guide.md)
|
||||||
├── device
|
├── device
|
||||||
├── upgrade
|
├── upgrade
|
||||||
├── cert
|
├── cert
|
||||||
@@ -238,8 +319,8 @@ tms:
|
|||||||
crypto-card:
|
crypto-card:
|
||||||
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
|
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
|
||||||
mode: ${TMS_CRYPTO_CARD_MODE:MOCK} # MOCK / JNA
|
mode: ${TMS_CRYPTO_CARD_MODE:MOCK} # MOCK / JNA
|
||||||
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:}
|
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:/home/tms/libs/libsdf_ukey_syd1408-x64.so.1.0.0}
|
||||||
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf}
|
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:sdf_ukey_syd1408}
|
||||||
```
|
```
|
||||||
|
|
||||||
- Internal PCIe debug APIs (strong-typed service):
|
- Internal PCIe debug APIs (strong-typed service):
|
||||||
@@ -280,8 +361,8 @@ tms:
|
|||||||
crypto-card:
|
crypto-card:
|
||||||
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
|
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
|
||||||
mode: ${TMS_CRYPTO_CARD_MODE:JNA} # MOCK / JNA
|
mode: ${TMS_CRYPTO_CARD_MODE:JNA} # MOCK / JNA
|
||||||
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:}
|
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:/home/tms/libs/libsdf_ukey_syd1408-x64.so.1.0.0}
|
||||||
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf}
|
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:sdf_ukey_syd1408}
|
||||||
```
|
```
|
||||||
|
|
||||||
- JNA native mapping: `com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary`
|
- JNA native mapping: `com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary`
|
||||||
|
|||||||
@@ -6,8 +6,43 @@ server:
|
|||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
tms:
|
tms:
|
||||||
|
web:
|
||||||
|
cors:
|
||||||
|
enabled: true
|
||||||
|
allowed-origin-patterns:
|
||||||
|
- http://localhost:*
|
||||||
|
- http://127.0.0.1:*
|
||||||
|
allowed-methods:
|
||||||
|
- GET
|
||||||
|
- POST
|
||||||
|
- PUT
|
||||||
|
- DELETE
|
||||||
|
- OPTIONS
|
||||||
|
allowed-headers:
|
||||||
|
- Authorization
|
||||||
|
- Content-Type
|
||||||
|
- X-Requested-With
|
||||||
|
- X-Internal-Token
|
||||||
|
- X-App-Id
|
||||||
|
- X-Timestamp
|
||||||
|
- X-Nonce
|
||||||
|
- X-Signature
|
||||||
|
- X-Trace-Id
|
||||||
|
exposed-headers:
|
||||||
|
- X-Trace-Id
|
||||||
|
allow-credentials: true
|
||||||
|
max-age-seconds: 3600
|
||||||
|
upgrade:
|
||||||
|
staging-root-dir: /home/tmp/tms-upgrade-staging
|
||||||
|
log-dir: /home/tms/tmp/tms-upgrade-logs
|
||||||
|
signature-public-key-base64: change-me-base64-public-key-blob
|
||||||
security:
|
security:
|
||||||
internal-token: change-me-internal-token
|
internal-token: change-me-internal-token
|
||||||
|
internal-auth:
|
||||||
|
enabled: true
|
||||||
|
debug-role-code: KEY_ADMIN
|
||||||
|
debug-auth-level: FULL
|
||||||
|
debug-session-token: DEBUG-BYPASS
|
||||||
openapi:
|
openapi:
|
||||||
timestamp-skew-seconds: 300
|
timestamp-skew-seconds: 300
|
||||||
clients:
|
clients:
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ mvn -q -DskipTests package
|
|||||||
### 6.2 创建运行目录
|
### 6.2 创建运行目录
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mkdir -p /home/tms/{bin,config,scripts,logs,run,tmp,uploads}
|
sudo mkdir -p /home/tms/{bin,config,scripts,logs,run,tmp,uploads,libs}
|
||||||
sudo chown -R "$(whoami)":"$(whoami)" /home/tms
|
sudo chown -R "$(whoami)":"$(whoami)" /home/tms
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -165,6 +165,7 @@ ls -l /home/tms/config/application.yml
|
|||||||
|
|
||||||
TMS 从以下位置加载外部配置:
|
TMS 从以下位置加载外部配置:
|
||||||
- `/home/tms/config/application.yml`
|
- `/home/tms/config/application.yml`
|
||||||
|
- 显式设置 `SPRING_PROFILES_ACTIVE` 时,额外加载 `/home/tms/config/application-\${SPRING_PROFILES_ACTIVE}.yml`
|
||||||
|
|
||||||
运行控制脚本:
|
运行控制脚本:
|
||||||
- [tms.sh](/Users/waner/Work/CISD/文档/tms-framework/scripts/tms.sh)
|
- [tms.sh](/Users/waner/Work/CISD/文档/tms-framework/scripts/tms.sh)
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# 标准收发器离线升级包最小样例
|
||||||
|
|
||||||
|
本目录提供 `STANDARD_APP` 离线升级包的最小示例骨架,用于对齐打包方、后端和联调流程。
|
||||||
|
|
||||||
|
目录结构:
|
||||||
|
|
||||||
|
```text
|
||||||
|
standard-app/
|
||||||
|
├── manifest.json
|
||||||
|
└── payload/
|
||||||
|
└── scripts/
|
||||||
|
└── orchestrator.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- 本目录中的 `manifest.json` 使用了占位符 `__PAYLOAD_SHA256__`
|
||||||
|
- 真正打包前,需要先对 `payload.zip` 计算 `SHA-256`,再替换该字段
|
||||||
|
- `signature.sig` 不放在仓库示例里,必须由打包方使用“固件完整性密钥”私钥在打包阶段生成
|
||||||
|
|
||||||
|
推荐打包步骤:
|
||||||
|
|
||||||
|
1. 进入当前示例目录
|
||||||
|
2. 将 `payload/` 压缩为 `payload.zip`
|
||||||
|
3. 计算 `payload.zip` 的 `SHA-256`
|
||||||
|
4. 用实际摘要替换 `manifest.json` 中的 `__PAYLOAD_SHA256__`
|
||||||
|
5. 对 `manifest.json` 原始字节生成 `signature.sig`
|
||||||
|
6. 将 `manifest.json`、`signature.sig`、`payload.zip` 压缩成最终 `upgrade-package.zip`
|
||||||
|
|
||||||
|
参考命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd docs/examples/upgrade-package/standard-app
|
||||||
|
|
||||||
|
zip -rq payload.zip payload
|
||||||
|
PAYLOAD_SHA256="$(shasum -a 256 payload.zip | awk '{print $1}')"
|
||||||
|
sed "s/__PAYLOAD_SHA256__/${PAYLOAD_SHA256}/g" manifest.json > manifest.generated.json
|
||||||
|
|
||||||
|
# 这里改为公司正式签名工具,生成 manifest.generated.json 对应的 signature.sig
|
||||||
|
# sign-manifest manifest.generated.json > signature.sig
|
||||||
|
|
||||||
|
zip -j upgrade-package.zip manifest.generated.json signature.sig payload.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
联调时建议:
|
||||||
|
|
||||||
|
- 先用这个目录骨架做一个 `STANDARD_APP` 预检样包
|
||||||
|
- `orchestrator.sh` 可以先只输出日志并返回 `0`
|
||||||
|
- 等预检、建任务、执行链路跑通后,再替换成真实升级脚本
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"packageFormatVersion": 1,
|
||||||
|
"packageId": "PKG-20260319-STANDARD-001",
|
||||||
|
"targetComponent": "STANDARD_APP",
|
||||||
|
"targetVersion": "V1.3.2",
|
||||||
|
"minCompatibleVersion": "V1.3.0",
|
||||||
|
"description": "标准收发器企业版离线升级包最小样例",
|
||||||
|
"createdAt": "2026-03-19T16:30:00+08:00",
|
||||||
|
"orchestrator": "scripts/orchestrator.sh",
|
||||||
|
"fileChecksums": {
|
||||||
|
"payloadZip": "__PAYLOAD_SHA256__"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TASK_ID="${1:-UNKNOWN}"
|
||||||
|
|
||||||
|
echo "[upgrade] task=${TASK_ID} phase=backup message=start backup placeholder"
|
||||||
|
echo "[upgrade] task=${TASK_ID} phase=stop-service message=stop service placeholder"
|
||||||
|
echo "[upgrade] task=${TASK_ID} phase=deploy message=deploy placeholder"
|
||||||
|
echo "[upgrade] task=${TASK_ID} phase=health-check message=health check placeholder"
|
||||||
|
echo "[upgrade] task=${TASK_ID} phase=done message=upgrade completed"
|
||||||
+292
-48
@@ -1,70 +1,314 @@
|
|||||||
-- -----------------------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
||||||
-- TMS 基础库结构(TiDB/MySQL)
|
-- TMS 最终库结构初始化脚本
|
||||||
-- 适用范围:当前已实现的初始化任务、步骤、设备节点、用户表
|
-- 适用范围:新库初始化
|
||||||
|
-- 数据库:TiDB / MySQL 8+
|
||||||
|
--
|
||||||
|
-- 说明:
|
||||||
|
-- 1. 本文件按当前项目最终表结构整理,适合“空库初始化”。
|
||||||
|
-- 2. 不再按 V1-V11 逐步执行 ALTER / RENAME,避免初始化时出现兼容性问题。
|
||||||
|
-- 3. 若用于已有库升级,请继续使用 Flyway migration,而不是本文件。
|
||||||
-- -----------------------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
-- 1) 建库(如已存在则跳过)
|
|
||||||
CREATE DATABASE IF NOT EXISTS tms
|
CREATE DATABASE IF NOT EXISTS tms
|
||||||
DEFAULT CHARACTER SET utf8mb4
|
DEFAULT CHARACTER SET utf8mb4
|
||||||
COLLATE utf8mb4_general_ci;
|
COLLATE utf8mb4_general_ci;
|
||||||
|
|
||||||
USE tms;
|
USE tms;
|
||||||
|
|
||||||
-- 2) 初始化任务主表
|
-- -----------------------------------------------------------------------------
|
||||||
|
-- 初始化任务
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS tms_init_task (
|
CREATE TABLE IF NOT EXISTS tms_init_task (
|
||||||
id BIGINT PRIMARY KEY COMMENT '主键ID',
|
id BIGINT PRIMARY KEY,
|
||||||
task_id VARCHAR(64) NOT NULL COMMENT '任务业务ID',
|
task_id VARCHAR(64) NOT NULL,
|
||||||
version VARCHAR(32) NOT NULL COMMENT 'CIPS版本',
|
task_type VARCHAR(32) NOT NULL DEFAULT 'INIT' COMMENT '任务类型:INIT/RESET',
|
||||||
status VARCHAR(32) NOT NULL COMMENT '任务状态',
|
version VARCHAR(32) NOT NULL,
|
||||||
product_type VARCHAR(16) NULL COMMENT '产品版本: enterprise/interbank/lite_direct',
|
status VARCHAR(32) NOT NULL,
|
||||||
org_code VARCHAR(32) NULL COMMENT '机构号',
|
product_type VARCHAR(16) NULL,
|
||||||
mq_type VARCHAR(32) NULL COMMENT '消息队列类型',
|
org_code VARCHAR(32) NULL,
|
||||||
deploy_mode VARCHAR(16) NULL COMMENT '部署模式: single/double/four',
|
mq_type VARCHAR(32) NULL,
|
||||||
init_plan_json LONGTEXT NULL COMMENT '初始化计划快照(JSON)',
|
deploy_mode VARCHAR(16) NULL,
|
||||||
create_time DATETIME(3) NOT NULL COMMENT '创建时间',
|
init_plan_json LONGTEXT NULL,
|
||||||
update_time DATETIME(3) NOT NULL COMMENT '更新时间',
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
UNIQUE KEY uk_tms_init_task_task_id (task_id)
|
UNIQUE KEY uk_tms_init_task_task_id (task_id)
|
||||||
) COMMENT='初始化任务表';
|
);
|
||||||
|
|
||||||
-- 3) 初始化任务步骤表
|
|
||||||
CREATE TABLE IF NOT EXISTS tms_init_task_step (
|
CREATE TABLE IF NOT EXISTS tms_init_task_step (
|
||||||
id BIGINT PRIMARY KEY COMMENT '主键ID',
|
id BIGINT PRIMARY KEY,
|
||||||
task_id VARCHAR(64) NOT NULL COMMENT '任务业务ID',
|
task_id VARCHAR(64) NOT NULL,
|
||||||
step_no INT NOT NULL COMMENT '步骤序号',
|
step_no INT NOT NULL,
|
||||||
step_code VARCHAR(64) NOT NULL COMMENT '步骤编码',
|
step_code VARCHAR(64) NOT NULL,
|
||||||
status VARCHAR(32) NOT NULL COMMENT '步骤状态',
|
status VARCHAR(32) NOT NULL,
|
||||||
message VARCHAR(512) NULL COMMENT '步骤信息',
|
message VARCHAR(512) NULL,
|
||||||
command_line VARCHAR(2048) NULL COMMENT '实际执行命令',
|
command_line VARCHAR(2048) NULL,
|
||||||
log_path VARCHAR(512) NULL COMMENT '日志文件路径',
|
log_path VARCHAR(512) NULL,
|
||||||
exit_code INT NULL COMMENT '命令退出码',
|
exit_code INT NULL,
|
||||||
create_time DATETIME(3) NOT NULL COMMENT '创建时间',
|
create_time DATETIME(3) NOT NULL,
|
||||||
update_time DATETIME(3) NOT NULL COMMENT '更新时间',
|
update_time DATETIME(3) NOT NULL,
|
||||||
UNIQUE KEY uk_tms_init_task_step_task_no (task_id, step_no),
|
UNIQUE KEY uk_tms_init_task_step_task_no (task_id, step_no),
|
||||||
KEY idx_tms_init_task_step_task_id (task_id)
|
KEY idx_tms_init_task_step_task_id (task_id)
|
||||||
) COMMENT='初始化任务步骤表';
|
);
|
||||||
|
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
-- 认证与设备基础表
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
-- 4) 系统用户表(简化)
|
|
||||||
CREATE TABLE IF NOT EXISTS tms_auth_user (
|
CREATE TABLE IF NOT EXISTS tms_auth_user (
|
||||||
id BIGINT PRIMARY KEY COMMENT '主键ID',
|
id BIGINT PRIMARY KEY,
|
||||||
username VARCHAR(64) NOT NULL COMMENT '用户名',
|
username VARCHAR(64) NOT NULL,
|
||||||
display_name VARCHAR(128) NOT NULL COMMENT '显示名',
|
display_name VARCHAR(128) NOT NULL,
|
||||||
role VARCHAR(64) NOT NULL COMMENT '角色',
|
role VARCHAR(64) NOT NULL,
|
||||||
create_time DATETIME(3) NOT NULL COMMENT '创建时间',
|
create_time DATETIME(3) NOT NULL,
|
||||||
update_time DATETIME(3) NOT NULL COMMENT '更新时间',
|
update_time DATETIME(3) NOT NULL,
|
||||||
UNIQUE KEY uk_tms_auth_user_username (username)
|
UNIQUE KEY uk_tms_auth_user_username (username)
|
||||||
) COMMENT='系统用户表';
|
);
|
||||||
|
|
||||||
-- 5) 设备节点表
|
|
||||||
CREATE TABLE IF NOT EXISTS tms_device_node (
|
CREATE TABLE IF NOT EXISTS tms_device_node (
|
||||||
id BIGINT PRIMARY KEY COMMENT '主键ID',
|
id BIGINT PRIMARY KEY,
|
||||||
node_id VARCHAR(64) NOT NULL COMMENT '节点业务ID',
|
node_id VARCHAR(64) NOT NULL,
|
||||||
host VARCHAR(128) NOT NULL COMMENT '节点主机地址',
|
host VARCHAR(128) NOT NULL,
|
||||||
status VARCHAR(32) NOT NULL COMMENT '节点状态',
|
status VARCHAR(32) NOT NULL,
|
||||||
create_time DATETIME(3) NOT NULL COMMENT '创建时间',
|
create_time DATETIME(3) NOT NULL,
|
||||||
update_time DATETIME(3) NOT NULL COMMENT '更新时间',
|
update_time DATETIME(3) NOT NULL,
|
||||||
UNIQUE KEY uk_tms_device_node_node_id (node_id)
|
UNIQUE KEY uk_tms_device_node_node_id (node_id)
|
||||||
) COMMENT='设备节点表';
|
);
|
||||||
|
|
||||||
-- 6) 可选初始化数据(按需启用)
|
CREATE TABLE IF NOT EXISTS tms_file_record (
|
||||||
-- INSERT INTO tms_auth_user (id, username, display_name, role, create_time, update_time)
|
id BIGINT PRIMARY KEY,
|
||||||
-- VALUES (10001, 'admin', '系统管理员', 'ADMIN', NOW(3), NOW(3));
|
file_id VARCHAR(64) NOT NULL,
|
||||||
|
original_filename VARCHAR(255) NOT NULL,
|
||||||
|
storage_path VARCHAR(1024) NOT NULL,
|
||||||
|
status VARCHAR(32) NOT NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_tms_file_record_file_id (file_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
-- 设备软件版本
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_device_software_version (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
component_code VARCHAR(64) NOT NULL,
|
||||||
|
component_name VARCHAR(128) NOT NULL,
|
||||||
|
current_version VARCHAR(128) NOT NULL,
|
||||||
|
source_type VARCHAR(32) NOT NULL,
|
||||||
|
detected_at DATETIME NULL,
|
||||||
|
remarks VARCHAR(255) NULL,
|
||||||
|
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE KEY uk_tms_device_software_version_component_code (component_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO tms_device_software_version
|
||||||
|
(id, component_code, component_name, current_version, source_type, detected_at, remarks)
|
||||||
|
VALUES
|
||||||
|
(1001, 'RABBITMQ', '消息队列', 'RabbitMQ V3.8.21', 'MANUAL', NOW(), '出厂预置'),
|
||||||
|
(1002, 'TLQ', '消息队列', 'tonglink/Q V8.1.11', 'MANUAL', NOW(), '出厂预置'),
|
||||||
|
(1003, 'TIDB', '数据库', 'TiDB V8.1.0', 'MANUAL', NOW(), '出厂预置'),
|
||||||
|
(1004, 'NGINX', 'Nginx', 'Nginx V1.20', 'MANUAL', NOW(), '出厂预置'),
|
||||||
|
(1005, 'APP', '标准收发器企业版', '标准收发器企业版 V1.3.2', 'MANUAL', NOW(), '出厂预置'),
|
||||||
|
(1006, 'TMS', 'CISD终端管理服务', 'CISD终端管理服务 V1.0.0', 'MANUAL', NOW(), '出厂预置')
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
component_name = VALUES(component_name),
|
||||||
|
current_version = VALUES(current_version),
|
||||||
|
source_type = VALUES(source_type),
|
||||||
|
detected_at = VALUES(detected_at),
|
||||||
|
remarks = VALUES(remarks),
|
||||||
|
update_time = CURRENT_TIMESTAMP;
|
||||||
|
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
-- 升级任务
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS t_upgrade_task (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(64) NOT NULL,
|
||||||
|
upgrade_mode VARCHAR(16) NOT NULL,
|
||||||
|
target_component VARCHAR(32) NOT NULL,
|
||||||
|
package_file_id VARCHAR(64) NOT NULL,
|
||||||
|
package_name VARCHAR(255) NOT NULL,
|
||||||
|
package_hash VARCHAR(128) NOT NULL,
|
||||||
|
current_version VARCHAR(64) NOT NULL,
|
||||||
|
target_version VARCHAR(64) NOT NULL,
|
||||||
|
status VARCHAR(32) NOT NULL,
|
||||||
|
verify_passed TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
verify_message VARCHAR(1024) NULL,
|
||||||
|
manifest_json TEXT NULL,
|
||||||
|
detail_log_path VARCHAR(1024) NULL,
|
||||||
|
error_message VARCHAR(1024) NULL,
|
||||||
|
operator VARCHAR(64) NULL,
|
||||||
|
started_at DATETIME(3) NULL,
|
||||||
|
finished_at DATETIME(3) NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_t_upgrade_task_task_id (task_id),
|
||||||
|
KEY idx_t_upgrade_task_status (status),
|
||||||
|
KEY idx_t_upgrade_task_component (target_component),
|
||||||
|
KEY idx_t_upgrade_task_create_time (create_time)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
-- 新认证体系
|
||||||
|
-- -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_role_account (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
role_code VARCHAR(64) NOT NULL,
|
||||||
|
display_name VARCHAR(128) NOT NULL,
|
||||||
|
required_ukey_count INT NOT NULL,
|
||||||
|
password_hash VARCHAR(256) NOT NULL,
|
||||||
|
password_salt VARCHAR(128) NOT NULL,
|
||||||
|
status VARCHAR(32) NOT NULL,
|
||||||
|
need_change_password TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
failed_count INT NOT NULL DEFAULT 0,
|
||||||
|
locked_until DATETIME(3) NULL,
|
||||||
|
last_login_at DATETIME(3) NULL,
|
||||||
|
last_active_at DATETIME(3) NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_tms_role_account_role_code (role_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_role_ukey_binding (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
role_code VARCHAR(64) NOT NULL,
|
||||||
|
slot_no INT NOT NULL,
|
||||||
|
ukey_serial VARCHAR(128) NOT NULL,
|
||||||
|
ukey_pubkey TEXT NOT NULL,
|
||||||
|
issuer_sign TEXT NULL,
|
||||||
|
status VARCHAR(32) NOT NULL,
|
||||||
|
bound_at DATETIME(3) NOT NULL,
|
||||||
|
unbound_at DATETIME(3) NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_tms_role_ukey_binding_role_slot (role_code, slot_no),
|
||||||
|
KEY idx_tms_role_ukey_binding_role_status (role_code, status)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_auth_session (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
session_token VARCHAR(128) NOT NULL,
|
||||||
|
role_code VARCHAR(64) NOT NULL,
|
||||||
|
auth_level VARCHAR(32) NOT NULL,
|
||||||
|
issued_at DATETIME(3) NOT NULL,
|
||||||
|
last_active_at DATETIME(3) NOT NULL,
|
||||||
|
expires_at DATETIME(3) NOT NULL,
|
||||||
|
logout_at DATETIME(3) NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_tms_auth_session_token (session_token),
|
||||||
|
KEY idx_tms_auth_session_role_code (role_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_auth_challenge (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
challenge_id VARCHAR(128) NOT NULL,
|
||||||
|
role_code VARCHAR(64) NOT NULL,
|
||||||
|
purpose VARCHAR(32) NOT NULL,
|
||||||
|
nonce VARCHAR(256) NOT NULL,
|
||||||
|
expires_at DATETIME(3) NOT NULL,
|
||||||
|
used TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
UNIQUE KEY uk_tms_auth_challenge_challenge_id (challenge_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tms_auth_audit_log (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
event_type VARCHAR(64) NOT NULL,
|
||||||
|
role_code VARCHAR(64) NULL,
|
||||||
|
operator_role_code VARCHAR(64) NULL,
|
||||||
|
result VARCHAR(32) NOT NULL,
|
||||||
|
detail_json JSON NULL,
|
||||||
|
remote_ip VARCHAR(64) NULL,
|
||||||
|
create_time DATETIME(3) NOT NULL,
|
||||||
|
update_time DATETIME(3) NOT NULL,
|
||||||
|
KEY idx_tms_auth_audit_log_event_type (event_type),
|
||||||
|
KEY idx_tms_auth_audit_log_role_code (role_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO tms_role_account (
|
||||||
|
id,
|
||||||
|
role_code,
|
||||||
|
display_name,
|
||||||
|
required_ukey_count,
|
||||||
|
password_hash,
|
||||||
|
password_salt,
|
||||||
|
status,
|
||||||
|
need_change_password,
|
||||||
|
failed_count,
|
||||||
|
locked_until,
|
||||||
|
last_login_at,
|
||||||
|
last_active_at,
|
||||||
|
create_time,
|
||||||
|
update_time
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
11001,
|
||||||
|
'SUPER_ADMIN',
|
||||||
|
'超级管理员',
|
||||||
|
3,
|
||||||
|
'Viuew8WE+qziUZwGGU0x25cUpzsTF+QvQFU0uhb+yVA=',
|
||||||
|
'init-super-admin-salt-20260325',
|
||||||
|
'UNENABLED',
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CURRENT_TIMESTAMP(3),
|
||||||
|
CURRENT_TIMESTAMP(3)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
11002,
|
||||||
|
'KEY_ADMIN',
|
||||||
|
'密钥管理员',
|
||||||
|
2,
|
||||||
|
'/xqmDy3A/q9X5p7XWznIPSBabQ6bxTLAPgtHQ6Be33c=',
|
||||||
|
'init-key-admin-salt-20260325',
|
||||||
|
'ACTIVE',
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CURRENT_TIMESTAMP(3),
|
||||||
|
CURRENT_TIMESTAMP(3)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
11003,
|
||||||
|
'AUDIT_ADMIN',
|
||||||
|
'审计管理员',
|
||||||
|
1,
|
||||||
|
'j/J1LKyUOzVEJfbbHe2dwKBKNdabRk502olk/LWIwhg=',
|
||||||
|
'init-audit-admin-salt-20260325',
|
||||||
|
'UNENABLED',
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CURRENT_TIMESTAMP(3),
|
||||||
|
CURRENT_TIMESTAMP(3)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
11004,
|
||||||
|
'OPS_ADMIN',
|
||||||
|
'运维管理员',
|
||||||
|
1,
|
||||||
|
'2e9F4aCgsDb+AuD1LrBEqEg8yjy3ODo27UHtx06vj/A=',
|
||||||
|
'init-ops-admin-salt-20260325',
|
||||||
|
'UNENABLED',
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CURRENT_TIMESTAMP(3),
|
||||||
|
CURRENT_TIMESTAMP(3)
|
||||||
|
);
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# TMS 初始化 SQL 执行说明
|
||||||
|
|
||||||
|
当前推荐使用 [tms_schema_full.sql](/Users/waner/Work/CISD/文档/tms-framework/docs/sql/tms_schema_full.sql)。
|
||||||
|
|
||||||
|
这份脚本已经整理成“最终库结构初始化版”,适合空库直接初始化,不再按 migration 逐步执行 `ALTER / RENAME`。
|
||||||
|
|
||||||
|
如果你在 TiDB 客户端里一次性执行整份文件,出现下面这类报错:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SQL Error [8130] [HY000]: client has multi-statement capability disabled
|
||||||
|
```
|
||||||
|
|
||||||
|
这不是 SQL 内容本身错误,而是“客户端把整份脚本作为一次多语句请求发送”,而当前 TiDB 连接未开启 multi-statement。
|
||||||
|
|
||||||
|
## 推荐做法
|
||||||
|
|
||||||
|
### 方式一:用脚本执行模式运行最终初始化脚本
|
||||||
|
|
||||||
|
优先用客户端的 `Run Script` / `Execute Script` 模式执行:
|
||||||
|
|
||||||
|
- [tms_schema_full.sql](/Users/waner/Work/CISD/文档/tms-framework/docs/sql/tms_schema_full.sql)
|
||||||
|
|
||||||
|
### 方式二:用“脚本执行”而不是“单次执行”
|
||||||
|
|
||||||
|
如果你的客户端支持 `Run Script` / `Execute Script`,优先用脚本模式。
|
||||||
|
脚本模式通常会把每条语句分开发送,而不是整份文件一次发给数据库。
|
||||||
|
|
||||||
|
### 方式三:使用命令行客户端导入
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -h <host> -P <port> -u <user> -p tms < /path/to/tms_schema_full.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
或者先登录后:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
source /path/to/tms_schema_full.sql;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式四:实在只能单条执行时
|
||||||
|
|
||||||
|
先执行:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE IF NOT EXISTS tms
|
||||||
|
DEFAULT CHARACTER SET utf8mb4
|
||||||
|
COLLATE utf8mb4_general_ci;
|
||||||
|
|
||||||
|
USE tms;
|
||||||
|
```
|
||||||
|
|
||||||
|
然后把 [tms_schema_full.sql](/Users/waner/Work/CISD/文档/tms-framework/docs/sql/tms_schema_full.sql) 中的语句按分号逐条执行。
|
||||||
|
|
||||||
|
## 不推荐但可选
|
||||||
|
|
||||||
|
你也可以按报错提示开启:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SET GLOBAL tidb_multi_statement_mode='ON';
|
||||||
|
```
|
||||||
|
|
||||||
|
但这会影响实例级行为,有安全风险,不建议为了初始化脚本临时这么做,除非你明确知道数据库侧的风险边界并且由 DBA 允许。
|
||||||
|
|
||||||
|
## 当前默认账号种子
|
||||||
|
|
||||||
|
脚本已经包含 4 个固定角色账号:
|
||||||
|
|
||||||
|
- `SUPER_ADMIN`
|
||||||
|
- `KEY_ADMIN`
|
||||||
|
- `AUDIT_ADMIN`
|
||||||
|
- `OPS_ADMIN`
|
||||||
|
|
||||||
|
默认口令均为 `12345678`,其中:
|
||||||
|
|
||||||
|
- `KEY_ADMIN` 默认 `ACTIVE`
|
||||||
|
- 其他角色默认 `UNENABLED`
|
||||||
|
- 所有角色 `need_change_password = 1`
|
||||||
+2427
File diff suppressed because it is too large
Load Diff
@@ -105,6 +105,16 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<parameters>true</parameters>
|
<parameters>true</parameters>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
STANDARD_HOME_DIR="${STANDARD_HOME_DIR:?STANDARD_HOME_DIR is required}"
|
||||||
|
STANDARD_RUN_USER="${STANDARD_RUN_USER:?STANDARD_RUN_USER is required}"
|
||||||
|
|
||||||
|
if [ -x "${STANDARD_HOME_DIR}/cmsp/stop_cmsp.sh" ]; then
|
||||||
|
su - "${STANDARD_RUN_USER}" -s /bin/bash "${STANDARD_HOME_DIR}/cmsp/stop_cmsp.sh" || true
|
||||||
|
else
|
||||||
|
pkill -f "${STANDARD_HOME_DIR}/cmsp" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -x "${STANDARD_HOME_DIR}/cmtp/stop_cmtp.sh" ]; then
|
||||||
|
su - "${STANDARD_RUN_USER}" -s /bin/bash "${STANDARD_HOME_DIR}/cmtp/stop_cmtp.sh" || true
|
||||||
|
else
|
||||||
|
pkill -f "${STANDARD_HOME_DIR}/cmtp" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if pgrep -f "/usr/local/nginx/sbin/nginx" >/dev/null; then
|
||||||
|
/usr/local/nginx/sbin/nginx -s stop || pkill -f "/usr/local/nginx/sbin/nginx" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
systemctl stop rabbitmq-server >/dev/null 2>&1 || true
|
||||||
+21
-9
@@ -22,7 +22,7 @@ PID_FILE="${PID_FILE:-${RUN_DIR}/${APP_NAME}.pid}"
|
|||||||
OUT_LOG="${OUT_LOG:-${LOG_DIR}/${APP_NAME}.out.log}"
|
OUT_LOG="${OUT_LOG:-${LOG_DIR}/${APP_NAME}.out.log}"
|
||||||
ERR_LOG="${ERR_LOG:-${LOG_DIR}/${APP_NAME}.err.log}"
|
ERR_LOG="${ERR_LOG:-${LOG_DIR}/${APP_NAME}.err.log}"
|
||||||
|
|
||||||
SPRING_PROFILES_ACTIVE="${SPRING_PROFILES_ACTIVE:-prod}"
|
SPRING_PROFILES_ACTIVE="${SPRING_PROFILES_ACTIVE:-}"
|
||||||
JAVA_BIN="${JAVA_BIN:-java}"
|
JAVA_BIN="${JAVA_BIN:-java}"
|
||||||
JAVA_OPTS="${JAVA_OPTS:- -Xms512m -Xmx1024m}"
|
JAVA_OPTS="${JAVA_OPTS:- -Xms512m -Xmx1024m}"
|
||||||
ALLOW_MISSING_EXTERNAL_CONFIG="${ALLOW_MISSING_EXTERNAL_CONFIG:-false}"
|
ALLOW_MISSING_EXTERNAL_CONFIG="${ALLOW_MISSING_EXTERNAL_CONFIG:-false}"
|
||||||
@@ -87,15 +87,27 @@ start_app() {
|
|||||||
echo "[INFO] starting ${APP_NAME}"
|
echo "[INFO] starting ${APP_NAME}"
|
||||||
echo "[INFO] app home: ${APP_HOME}"
|
echo "[INFO] app home: ${APP_HOME}"
|
||||||
echo "[INFO] jar path: ${JAR_PATH}"
|
echo "[INFO] jar path: ${JAR_PATH}"
|
||||||
echo "[INFO] profile: ${SPRING_PROFILES_ACTIVE}"
|
if [[ -n "${SPRING_PROFILES_ACTIVE}" ]]; then
|
||||||
|
echo "[INFO] profile override: ${SPRING_PROFILES_ACTIVE}"
|
||||||
|
else
|
||||||
|
echo "[INFO] profile override: <none>"
|
||||||
|
fi
|
||||||
echo "[INFO] external config dir: ${CONF_DIR}"
|
echo "[INFO] external config dir: ${CONF_DIR}"
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
if [[ -n "${SPRING_PROFILES_ACTIVE}" ]]; then
|
||||||
nohup "${JAVA_BIN}" ${JAVA_OPTS} \
|
# shellcheck disable=SC2086
|
||||||
-jar "${JAR_PATH}" \
|
nohup "${JAVA_BIN}" ${JAVA_OPTS} \
|
||||||
--spring.profiles.active="${SPRING_PROFILES_ACTIVE}" \
|
-jar "${JAR_PATH}" \
|
||||||
--spring.config.additional-location="${cfg_location}" \
|
--spring.profiles.active="${SPRING_PROFILES_ACTIVE}" \
|
||||||
>"${OUT_LOG}" 2>"${ERR_LOG}" &
|
--spring.config.additional-location="${cfg_location}" \
|
||||||
|
>"${OUT_LOG}" 2>"${ERR_LOG}" &
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
nohup "${JAVA_BIN}" ${JAVA_OPTS} \
|
||||||
|
-jar "${JAR_PATH}" \
|
||||||
|
--spring.config.additional-location="${cfg_location}" \
|
||||||
|
>"${OUT_LOG}" 2>"${ERR_LOG}" &
|
||||||
|
fi
|
||||||
|
|
||||||
local pid="$!"
|
local pid="$!"
|
||||||
echo "${pid}" > "${PID_FILE}"
|
echo "${pid}" > "${PID_FILE}"
|
||||||
@@ -160,7 +172,7 @@ Environment variables:
|
|||||||
CONF_DIR default: <app_home>/config
|
CONF_DIR default: <app_home>/config
|
||||||
RUN_DIR default: <app_home>/run
|
RUN_DIR default: <app_home>/run
|
||||||
LOG_DIR default: <app_home>/logs
|
LOG_DIR default: <app_home>/logs
|
||||||
SPRING_PROFILES_ACTIVE default: prod
|
SPRING_PROFILES_ACTIVE optional: override Spring profile
|
||||||
JAVA_BIN default: java
|
JAVA_BIN default: java
|
||||||
JAVA_OPTS default: -Xms512m -Xmx1024m
|
JAVA_OPTS default: -Xms512m -Xmx1024m
|
||||||
ALLOW_MISSING_EXTERNAL_CONFIG default: false
|
ALLOW_MISSING_EXTERNAL_CONFIG default: false
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.cisd.tms.common.config;
|
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.internal.InternalApiAuthInterceptor;
|
||||||
import com.cisd.tms.security.openapi.OpenApiSignAuthInterceptor;
|
import com.cisd.tms.security.openapi.OpenApiSignAuthInterceptor;
|
||||||
import com.cisd.tms.common.util.TraceIdUtil;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
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.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
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 {
|
public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
private final InternalApiAuthInterceptor internalApiAuthInterceptor;
|
private final InternalApiAuthInterceptor internalApiAuthInterceptor;
|
||||||
|
private final InternalAuthorizationInterceptor internalAuthorizationInterceptor;
|
||||||
private final OpenApiSignAuthInterceptor openApiSignAuthInterceptor;
|
private final OpenApiSignAuthInterceptor openApiSignAuthInterceptor;
|
||||||
|
private final TmsCorsProperties corsProperties;
|
||||||
|
|
||||||
public WebMvcConfig(
|
public WebMvcConfig(
|
||||||
InternalApiAuthInterceptor internalApiAuthInterceptor,
|
InternalApiAuthInterceptor internalApiAuthInterceptor,
|
||||||
OpenApiSignAuthInterceptor openApiSignAuthInterceptor
|
InternalAuthorizationInterceptor internalAuthorizationInterceptor,
|
||||||
|
OpenApiSignAuthInterceptor openApiSignAuthInterceptor,
|
||||||
|
TmsCorsProperties corsProperties
|
||||||
) {
|
) {
|
||||||
this.internalApiAuthInterceptor = internalApiAuthInterceptor;
|
this.internalApiAuthInterceptor = internalApiAuthInterceptor;
|
||||||
|
this.internalAuthorizationInterceptor = internalAuthorizationInterceptor;
|
||||||
this.openApiSignAuthInterceptor = openApiSignAuthInterceptor;
|
this.openApiSignAuthInterceptor = openApiSignAuthInterceptor;
|
||||||
|
this.corsProperties = corsProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -56,10 +65,31 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
.addPathPatterns("/api/**")
|
.addPathPatterns("/api/**")
|
||||||
.excludePathPatterns(
|
.excludePathPatterns(
|
||||||
"/api/v1/device/status",
|
"/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)
|
registry.addInterceptor(openApiSignAuthInterceptor)
|
||||||
.addPathPatterns("/openapi/**");
|
.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 {
|
public class TmsSecurityProperties {
|
||||||
|
|
||||||
private String internalToken = "change-me-internal-token";
|
private String internalToken = "change-me-internal-token";
|
||||||
|
private final InternalAuth internalAuth = new InternalAuth();
|
||||||
private final Openapi openapi = new Openapi();
|
private final Openapi openapi = new Openapi();
|
||||||
|
|
||||||
public String getInternalToken() {
|
public String getInternalToken() {
|
||||||
@@ -18,10 +19,53 @@ public class TmsSecurityProperties {
|
|||||||
this.internalToken = internalToken;
|
this.internalToken = internalToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InternalAuth getInternalAuth() {
|
||||||
|
return internalAuth;
|
||||||
|
}
|
||||||
|
|
||||||
public Openapi getOpenapi() {
|
public Openapi getOpenapi() {
|
||||||
return openapi;
|
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 {
|
public static class Openapi {
|
||||||
private long timestampSkewSeconds = 300;
|
private long timestampSkewSeconds = 300;
|
||||||
private Map<String, String> clients = new HashMap<>();
|
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.Native;
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.ptr.PointerByReference;
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -33,6 +34,7 @@ public class PcieSessionTemplate {
|
|||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
private volatile PcieNativeLibrary nativeLibrary;
|
private volatile PcieNativeLibrary nativeLibrary;
|
||||||
|
private volatile Pointer sharedDeviceHandle;
|
||||||
|
|
||||||
public PcieSessionTemplate(CryptoCardProperties properties, PcieErrorMapper errorMapper) {
|
public PcieSessionTemplate(CryptoCardProperties properties, PcieErrorMapper errorMapper) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
@@ -42,32 +44,22 @@ public class PcieSessionTemplate {
|
|||||||
public <T> T withDevice(String apiName, DeviceCallback<T> callback) {
|
public <T> T withDevice(String apiName, DeviceCallback<T> callback) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
PcieNativeLibrary lib = ensureLibraryLoaded();
|
PcieNativeLibrary lib = ensureLibraryLoaded();
|
||||||
|
Pointer device = ensureSharedDeviceOpened(apiName, lib);
|
||||||
PointerByReference deviceRef = new PointerByReference();
|
return callback.apply(lib, device);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T withSession(String apiName, SessionCallback<T> callback) {
|
public <T> T withSession(String apiName, SessionCallback<T> callback) {
|
||||||
return withDevice(apiName, (lib, deviceHandle) -> {
|
synchronized (lock) {
|
||||||
PointerByReference sessionRef = new PointerByReference();
|
PcieNativeLibrary lib = ensureLibraryLoaded();
|
||||||
Pointer ph = new Memory(8L);
|
Pointer deviceHandle = ensureSharedDeviceOpened(apiName, lib);
|
||||||
sessionRef.setValue(ph);
|
Pointer session = tryOpenSession(apiName, lib, deviceHandle);
|
||||||
int openSessionRc = lib.SDF_OpenSession(deviceHandle, sessionRef);
|
if (session == null) {
|
||||||
ensureSuccess(apiName + ":SDF_OpenSession", openSessionRc);
|
resetSharedDevice(lib);
|
||||||
|
deviceHandle = ensureSharedDeviceOpened(apiName, lib);
|
||||||
|
session = openSessionOrThrow(apiName, lib, deviceHandle);
|
||||||
|
}
|
||||||
|
|
||||||
Pointer session = sessionRef.getValue();
|
|
||||||
try {
|
try {
|
||||||
return callback.apply(lib, deviceHandle, session);
|
return callback.apply(lib, deviceHandle, session);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -76,7 +68,7 @@ public class PcieSessionTemplate {
|
|||||||
log.warn("{} close session failed: {}", apiName, errorMapper.toMessage(closeSessionRc));
|
log.warn("{} close session failed: {}", apiName, errorMapper.toMessage(closeSessionRc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ensureSuccess(String apiName, int retCode) {
|
public void ensureSuccess(String apiName, int retCode) {
|
||||||
@@ -85,6 +77,13 @@ public class PcieSessionTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
void closeSharedDevice() {
|
||||||
|
synchronized (lock) {
|
||||||
|
closeSharedDevice(libOrNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private PcieNativeLibrary ensureLibraryLoaded() {
|
private PcieNativeLibrary ensureLibraryLoaded() {
|
||||||
PcieNativeLibrary cached = nativeLibrary;
|
PcieNativeLibrary cached = nativeLibrary;
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
@@ -116,4 +115,55 @@ public class PcieSessionTemplate {
|
|||||||
return nativeLibrary;
|
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_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);
|
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_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_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);
|
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;
|
import com.sun.jna.Structure;
|
||||||
|
|
||||||
@Structure.FieldOrder({
|
@Structure.FieldOrder({
|
||||||
|
"type",
|
||||||
"level",
|
"level",
|
||||||
"devCount",
|
"devCount",
|
||||||
"rsaKeyCount",
|
"rsaKeyCount",
|
||||||
@@ -13,6 +14,7 @@ import com.sun.jna.Structure;
|
|||||||
})
|
})
|
||||||
public class SdfeDeviceConf extends Structure {
|
public class SdfeDeviceConf extends Structure {
|
||||||
|
|
||||||
|
public int type;
|
||||||
public int level;
|
public int level;
|
||||||
public int devCount;
|
public int devCount;
|
||||||
public int rsaKeyCount;
|
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 {
|
public class DeviceConfResult {
|
||||||
|
|
||||||
|
private int type;
|
||||||
private int level;
|
private int level;
|
||||||
private int devCount;
|
private int devCount;
|
||||||
private int rsaKeyCount;
|
private int rsaKeyCount;
|
||||||
@@ -10,6 +11,14 @@ public class DeviceConfResult {
|
|||||||
private int sessKeyCount;
|
private int sessKeyCount;
|
||||||
private int fileSysCapacity;
|
private int fileSysCapacity;
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
public int getLevel() {
|
public int getLevel() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ public class DeviceInfoResult {
|
|||||||
private int symAlgAbility;
|
private int symAlgAbility;
|
||||||
private int hashAlgAbility;
|
private int hashAlgAbility;
|
||||||
private int bufferSize;
|
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() {
|
public String getIssuerName() {
|
||||||
return issuerName;
|
return issuerName;
|
||||||
@@ -92,4 +99,60 @@ public class DeviceInfoResult {
|
|||||||
public void setBufferSize(int bufferSize) {
|
public void setBufferSize(int bufferSize) {
|
||||||
this.bufferSize = 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;
|
package com.cisd.tms.integration.crypto.pcie.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
public class DeviceStatusResult {
|
public class DeviceStatusResult {
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
private byte[] statusData;
|
private byte[] statusData;
|
||||||
private int length;
|
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() {
|
public byte[] getStatusData() {
|
||||||
return statusData;
|
return statusData;
|
||||||
@@ -20,4 +41,148 @@ public class DeviceStatusResult {
|
|||||||
public void setLength(int length) {
|
public void setLength(int length) {
|
||||||
this.length = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-21
@@ -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.RsaRefPublicKey;
|
||||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfDeviceInfo;
|
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.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.SdfeKekComponent;
|
||||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent;
|
import com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent;
|
||||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfeLoginState;
|
import com.cisd.tms.integration.crypto.pcie.jna.SdfeLoginState;
|
||||||
@@ -129,6 +130,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
conf.read();
|
conf.read();
|
||||||
|
|
||||||
DeviceConfResult result = new DeviceConfResult();
|
DeviceConfResult result = new DeviceConfResult();
|
||||||
|
result.setType(conf.type);
|
||||||
result.setLevel(conf.level);
|
result.setLevel(conf.level);
|
||||||
result.setDevCount(conf.devCount);
|
result.setDevCount(conf.devCount);
|
||||||
result.setRsaKeyCount(conf.rsaKeyCount);
|
result.setRsaKeyCount(conf.rsaKeyCount);
|
||||||
@@ -158,6 +160,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
result.setSymAlgAbility(info.symAlgAbility);
|
result.setSymAlgAbility(info.symAlgAbility);
|
||||||
result.setHashAlgAbility(info.hashAlgAbility);
|
result.setHashAlgAbility(info.hashAlgAbility);
|
||||||
result.setBufferSize(info.bufferSize);
|
result.setBufferSize(info.bufferSize);
|
||||||
|
PcieDeviceInfoFormatter.enrich(result);
|
||||||
return 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
|
@Override
|
||||||
public void deviceSelfTest() {
|
public void deviceSelfTest() {
|
||||||
sessionTemplate.withSession("SDFE_DeviceSelfTest", (lib, deviceHandle, sessionHandle) -> {
|
sessionTemplate.withSession("SDFE_DeviceSelfTest", (lib, deviceHandle, sessionHandle) -> {
|
||||||
@@ -202,15 +239,16 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceStatusResult getDeviceStatus() {
|
public DeviceStatusResult getDeviceStatus() {
|
||||||
int size = 8;
|
|
||||||
|
|
||||||
return sessionTemplate.withSession("SDFE_DeviceStatusGet", (lib, deviceHandle, sessionHandle) -> {
|
return sessionTemplate.withSession("SDFE_DeviceStatusGet", (lib, deviceHandle, sessionHandle) -> {
|
||||||
Memory statusMemory = new Memory(8);
|
SdfeDeviceStatus status = new SdfeDeviceStatus();
|
||||||
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, statusMemory));
|
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, status));
|
||||||
|
status.read();
|
||||||
|
int size = status.size();
|
||||||
|
|
||||||
DeviceStatusResult result = new DeviceStatusResult();
|
DeviceStatusResult result = new DeviceStatusResult();
|
||||||
// result.setLength(size);
|
result.setLength(size);
|
||||||
result.setStatusData(statusMemory.getByteArray(0, size));
|
result.setStatusData(status.getPointer().getByteArray(0, size));
|
||||||
|
PcieDeviceStatusFormatter.enrich(result, status);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1611,15 +1649,9 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BackupDataResult backupLmkEx(int outBufferSize) {
|
public BackupDataResult backupLmkEx() {
|
||||||
int size = requirePositive("outBufferSize", outBufferSize);
|
|
||||||
|
|
||||||
return sessionTemplate.withSession("SDFE_BackupLMK_EX", (lib, deviceHandle, sessionHandle) -> {
|
return sessionTemplate.withSession("SDFE_BackupLMK_EX", (lib, deviceHandle, sessionHandle) -> {
|
||||||
SdfeLmkComponent output = new SdfeLmkComponent();
|
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));
|
sessionTemplate.ensureSuccess("SDFE_BackupLMK_EX", lib.SDFE_BackupLMK_EX(sessionHandle, output));
|
||||||
byte[] outputBytes = toBytes(output);
|
byte[] outputBytes = toBytes(output);
|
||||||
return toBackupResult("SDFE_BackupLMK_EX", outputBytes, outputBytes.length);
|
return toBackupResult("SDFE_BackupLMK_EX", outputBytes, outputBytes.length);
|
||||||
@@ -1781,8 +1813,11 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
|
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sessionTemplate.withSession("SDFE_ReadLMKComponent", (lib, deviceHandle, sessionHandle) -> {
|
sessionTemplate.withSession("SDFE_ReadUkeyLMKComponent", (lib, deviceHandle, sessionHandle) -> {
|
||||||
sessionTemplate.ensureSuccess("SDFE_ReadLMKComponent", lib.SDFE_ReadLMKComponent(sessionHandle, pin, pin.length));
|
sessionTemplate.ensureSuccess(
|
||||||
|
"SDFE_ReadUkeyLMKComponent",
|
||||||
|
lib.SDFE_ReadUkeyLMKComponent(sessionHandle, pin, pin.length)
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1813,8 +1848,11 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
|
byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sessionTemplate.withSession("SDFE_GenerateCertificate", (lib, deviceHandle, sessionHandle) -> {
|
sessionTemplate.withSession("SDFE_GenerateUkeyCertificate", (lib, deviceHandle, sessionHandle) -> {
|
||||||
sessionTemplate.ensureSuccess("SDFE_GenerateCertificate", lib.SDFE_GenerateCertificate(sessionHandle, pin, pin.length));
|
sessionTemplate.ensureSuccess(
|
||||||
|
"SDFE_GenerateUkeyCertificate",
|
||||||
|
lib.SDFE_GenerateUkeyCertificate(sessionHandle, pin, pin.length)
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1826,17 +1864,17 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
|||||||
public void logoutAdmin(int adminIndex) {
|
public void logoutAdmin(int adminIndex) {
|
||||||
int safeAdminIndex = requireByteRange("adminIndex", adminIndex);
|
int safeAdminIndex = requireByteRange("adminIndex", adminIndex);
|
||||||
|
|
||||||
sessionTemplate.withSession("SDFE_LoginoutAdmin", (lib, deviceHandle, sessionHandle) -> {
|
sessionTemplate.withSession("SDFE_LoginoutUkey", (lib, deviceHandle, sessionHandle) -> {
|
||||||
sessionTemplate.ensureSuccess("SDFE_LoginoutAdmin", lib.SDFE_LoginoutAdmin(sessionHandle, (byte) safeAdminIndex));
|
sessionTemplate.ensureSuccess("SDFE_LoginoutUkey", lib.SDFE_LoginoutUkey(sessionHandle, (byte) safeAdminIndex));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoginStatusResult loginStatus() {
|
public LoginStatusResult loginStatus() {
|
||||||
return sessionTemplate.withSession("SDFE_LoginStatus", (lib, deviceHandle, sessionHandle) -> {
|
return sessionTemplate.withSession("SDFE_UkeyLoginStatus", (lib, deviceHandle, sessionHandle) -> {
|
||||||
SdfeLoginState state = new SdfeLoginState();
|
SdfeLoginState state = new SdfeLoginState();
|
||||||
sessionTemplate.ensureSuccess("SDFE_LoginStatus", lib.SDFE_LoginStatus(sessionHandle, state));
|
sessionTemplate.ensureSuccess("SDFE_UkeyLoginStatus", lib.SDFE_UkeyLoginStatus(sessionHandle, state));
|
||||||
state.read();
|
state.read();
|
||||||
|
|
||||||
LoginStatusResult result = new LoginStatusResult();
|
LoginStatusResult result = new LoginStatusResult();
|
||||||
|
|||||||
+17
-4
@@ -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.PcieKeyState;
|
||||||
import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType;
|
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.AgreementDataAndKeyEccResult;
|
||||||
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
||||||
import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest;
|
import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest;
|
||||||
@@ -100,6 +101,19 @@ public class MockPcieCryptoService implements PcieCryptoService {
|
|||||||
requireNonEmptyBytes("newPin", newPin);
|
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
|
@Override
|
||||||
public void deviceSelfTest() {
|
public void deviceSelfTest() {
|
||||||
// no-op
|
// no-op
|
||||||
@@ -107,7 +121,7 @@ public class MockPcieCryptoService implements PcieCryptoService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceStatusResult getDeviceStatus() {
|
public DeviceStatusResult getDeviceStatus() {
|
||||||
int size = 8;
|
int size = new SdfeDeviceStatus().size();
|
||||||
DeviceStatusResult result = new DeviceStatusResult();
|
DeviceStatusResult result = new DeviceStatusResult();
|
||||||
result.setLength(size);
|
result.setLength(size);
|
||||||
result.setStatusData(new byte[size]);
|
result.setStatusData(new byte[size]);
|
||||||
@@ -679,9 +693,8 @@ public class MockPcieCryptoService implements PcieCryptoService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BackupDataResult backupLmkEx(int outBufferSize) {
|
public BackupDataResult backupLmkEx() {
|
||||||
int size = requirePositive("outBufferSize", outBufferSize);
|
return mockBackup(new com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent().size(), 0x11);
|
||||||
return mockBackup(size, 0x11);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ public interface PcieCryptoService {
|
|||||||
|
|
||||||
void initIdentify(byte[] oldPin, byte[] newPin);
|
void initIdentify(byte[] oldPin, byte[] newPin);
|
||||||
|
|
||||||
|
byte[] initializeMasterKey(byte[] oldPin, byte[] newPin);
|
||||||
|
|
||||||
void deviceSelfTest();
|
void deviceSelfTest();
|
||||||
|
|
||||||
DeviceStatusResult getDeviceStatus();
|
DeviceStatusResult getDeviceStatus();
|
||||||
@@ -209,7 +211,7 @@ public interface PcieCryptoService {
|
|||||||
|
|
||||||
byte[] exportLmkSeedMac();
|
byte[] exportLmkSeedMac();
|
||||||
|
|
||||||
BackupDataResult backupLmkEx(int outBufferSize);
|
BackupDataResult backupLmkEx();
|
||||||
|
|
||||||
void recoverLmkEx(byte[] lmkComponent);
|
void recoverLmkEx(byte[] lmkComponent);
|
||||||
|
|
||||||
|
|||||||
+146
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+81
@@ -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;
|
package com.cisd.tms.modules.auth.controller;
|
||||||
|
|
||||||
import com.cisd.tms.common.api.ApiResponse;
|
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.CurrentUserResponse;
|
||||||
import com.cisd.tms.modules.auth.dto.LoginRequest;
|
import com.cisd.tms.modules.auth.dto.LoginRequest;
|
||||||
import com.cisd.tms.modules.auth.dto.LoginResponse;
|
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.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.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -22,23 +30,108 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
private final AuthService authService;
|
private final AuthService authService;
|
||||||
|
private final AuthAdminService authAdminService;
|
||||||
|
|
||||||
public AuthController(AuthService authService) {
|
public AuthController(AuthService authService, AuthAdminService authAdminService) {
|
||||||
this.authService = authService;
|
this.authService = authService;
|
||||||
|
this.authAdminService = authAdminService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@Operation(summary = "内部用户登录", description = "校验用户名和密码,返回访问令牌及过期时间。")
|
@Operation(summary = "内部用户登录", description = "校验角色口令,可选校验 UKey 序列号,返回访问令牌和认证等级。")
|
||||||
public ApiResponse<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
|
public ApiResponse<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
|
||||||
return ApiResponse.success(authService.login(request));
|
return ApiResponse.success(authService.login(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/me")
|
@GetMapping("/me")
|
||||||
@Operation(summary = "查询当前用户", description = "根据请求头中的用户标识返回当前登录用户信息。")
|
@Operation(summary = "查询当前用户", description = "根据内部鉴权链路透传的当前角色标识返回当前登录用户信息。")
|
||||||
public ApiResponse<CurrentUserResponse> me(
|
public ApiResponse<CurrentUserResponse> me(HttpServletRequest request) {
|
||||||
@Parameter(description = "当前用户标识,来自内部鉴权链路透传的 X-User 请求头")
|
String user = (String) request.getAttribute(com.cisd.tms.security.internal.InternalApiAuthInterceptor.ATTR_ROLE_CODE);
|
||||||
@RequestHeader(value = "X-User", required = false) String user
|
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;
|
private String displayName;
|
||||||
@Schema(description = "角色标识", example = "ADMIN")
|
@Schema(description = "角色标识", example = "ADMIN")
|
||||||
private String role;
|
private String role;
|
||||||
|
@Schema(description = "当前会话等级", example = "FULL")
|
||||||
|
private String authLevel;
|
||||||
|
@Schema(description = "是否需要强制修改密码")
|
||||||
|
private Boolean needChangePassword;
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
@@ -35,4 +39,20 @@ public class CurrentUserResponse {
|
|||||||
public void setRole(String role) {
|
public void setRole(String role) {
|
||||||
this.role = 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 io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "内部登录请求")
|
@Schema(description = "内部登录请求")
|
||||||
public class LoginRequest {
|
public class LoginRequest {
|
||||||
|
|
||||||
@NotBlank(message = "username is required")
|
@NotBlank(message = "roleCode is required")
|
||||||
@Schema(description = "登录用户名", example = "admin")
|
@Schema(description = "角色编码", example = "KEY_ADMIN")
|
||||||
private String username;
|
private String roleCode;
|
||||||
|
|
||||||
@NotBlank(message = "password is required")
|
@NotBlank(message = "password is required")
|
||||||
@Schema(description = "登录密码", example = "P@ssw0rd")
|
@Schema(description = "登录密码", example = "P@ssw0rd")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
public String getUsername() {
|
@Schema(description = "UKey 序列号列表,完整登录时需传入角色要求数量的序列号")
|
||||||
return username;
|
private List<@NotBlank(message = "ukey serial must not be blank") String> ukeySerials;
|
||||||
|
|
||||||
|
public String getRoleCode() {
|
||||||
|
return roleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setRoleCode(String roleCode) {
|
||||||
this.username = username;
|
this.roleCode = roleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
@@ -29,4 +33,12 @@ public class LoginRequest {
|
|||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
this.password = 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 = "内部登录响应")
|
@Schema(description = "内部登录响应")
|
||||||
public class LoginResponse {
|
public class LoginResponse {
|
||||||
|
|
||||||
@Schema(description = "登录用户名", example = "admin")
|
@Schema(description = "角色编码", example = "KEY_ADMIN")
|
||||||
private String username;
|
private String roleCode;
|
||||||
@Schema(description = "访问令牌")
|
@Schema(description = "访问令牌")
|
||||||
private String token;
|
private String token;
|
||||||
|
@Schema(description = "认证等级", example = "FULL")
|
||||||
|
private String authLevel;
|
||||||
@Schema(description = "令牌过期时间", example = "2026-03-11T18:00:00+08:00")
|
@Schema(description = "令牌过期时间", example = "2026-03-11T18:00:00+08:00")
|
||||||
private String expiresAt;
|
private String expiresAt;
|
||||||
|
@Schema(description = "是否需要首次修改密码")
|
||||||
|
private Boolean needChangePassword;
|
||||||
|
|
||||||
public String getUsername() {
|
public String getRoleCode() {
|
||||||
return username;
|
return roleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setRoleCode(String roleCode) {
|
||||||
this.username = username;
|
this.roleCode = roleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
@@ -28,6 +32,14 @@ public class LoginResponse {
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAuthLevel() {
|
||||||
|
return authLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthLevel(String authLevel) {
|
||||||
|
this.authLevel = authLevel;
|
||||||
|
}
|
||||||
|
|
||||||
public String getExpiresAt() {
|
public String getExpiresAt() {
|
||||||
return expiresAt;
|
return expiresAt;
|
||||||
}
|
}
|
||||||
@@ -35,4 +47,12 @@ public class LoginResponse {
|
|||||||
public void setExpiresAt(String expiresAt) {
|
public void setExpiresAt(String expiresAt) {
|
||||||
this.expiresAt = 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);
|
||||||
|
}
|
||||||
+32
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+68
@@ -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;
|
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.CurrentUserResponse;
|
||||||
import com.cisd.tms.modules.auth.dto.LoginRequest;
|
import com.cisd.tms.modules.auth.dto.LoginRequest;
|
||||||
import com.cisd.tms.modules.auth.dto.LoginResponse;
|
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.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.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.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AuthService {
|
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.authUserRepository = authUserRepository;
|
||||||
|
this.authSessionRepository = authSessionRepository;
|
||||||
|
this.roleUkeyBindingRepository = roleUkeyBindingRepository;
|
||||||
|
this.passwordHasher = passwordHasher;
|
||||||
|
this.clock = clock;
|
||||||
|
this.tokenSupplier = tokenSupplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginResponse login(LoginRequest request) {
|
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();
|
LoginResponse response = new LoginResponse();
|
||||||
response.setUsername(request.getUsername());
|
response.setRoleCode(roleAccount.getRoleCode());
|
||||||
response.setToken("tms-" + UUID.randomUUID());
|
response.setAuthLevel(authLevel.name());
|
||||||
response.setExpiresAt(OffsetDateTime.now().plusHours(8).toString());
|
response.setToken(session.getSessionToken());
|
||||||
|
response.setExpiresAt(OffsetDateTime.of(session.getExpiresAt(), ZoneOffset.UTC).toString());
|
||||||
|
response.setNeedChangePassword(Boolean.TRUE.equals(roleAccount.getNeedChangePassword()));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CurrentUserResponse me(String username) {
|
public CurrentUserResponse me(String username) {
|
||||||
|
return me(username, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrentUserResponse me(String username, String sessionToken) {
|
||||||
String normalized = username == null || username.isBlank() ? "admin" : username;
|
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);
|
AuthUserEntity entity = authUserRepository.findByUsername(normalized).orElse(null);
|
||||||
|
|
||||||
CurrentUserResponse response = new CurrentUserResponse();
|
CurrentUserResponse response = new CurrentUserResponse();
|
||||||
@@ -43,4 +136,114 @@ public class AuthService {
|
|||||||
response.setRole(entity.getRole());
|
response.setRole(entity.getRole());
|
||||||
return response;
|
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.DeviceProfileService;
|
||||||
import com.cisd.tms.modules.device.service.DeviceRuntimeStatusService;
|
import com.cisd.tms.modules.device.service.DeviceRuntimeStatusService;
|
||||||
import com.cisd.tms.modules.device.service.DeviceService;
|
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.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -62,10 +63,8 @@ public class DeviceController {
|
|||||||
|
|
||||||
@PostMapping("/restart")
|
@PostMapping("/restart")
|
||||||
@Operation(summary = "重启设备服务", description = "受理设备重启请求,并记录触发操作的内部用户。")
|
@Operation(summary = "重启设备服务", description = "受理设备重启请求,并记录触发操作的内部用户。")
|
||||||
public ApiResponse<DeviceActionResponse> restart(
|
public ApiResponse<DeviceActionResponse> restart(HttpServletRequest request) {
|
||||||
@Parameter(description = "触发重启的操作人,来自内部鉴权链路透传的 X-User 请求头")
|
String operator = (String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE);
|
||||||
@RequestHeader(value = "X-User", required = false) String operator
|
|
||||||
) {
|
|
||||||
return ApiResponse.success(deviceService.restart(operator));
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+95
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user