角色和登录改动
This commit is contained in:
@@ -2,8 +2,9 @@ package com.cisd.tms.modules.auth.controller;
|
||||
|
||||
import com.cisd.tms.common.api.ApiResponse;
|
||||
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.enums.AuthLevel;
|
||||
import com.cisd.tms.modules.auth.enums.RoleCode;
|
||||
import com.cisd.tms.modules.auth.security.RequireInternalAuth;
|
||||
import com.cisd.tms.modules.auth.service.AuthAdminService;
|
||||
import com.cisd.tms.modules.mk.dto.UKeySignDTO;
|
||||
import com.cisd.tms.modules.mk.dto.UKeySignResult;
|
||||
@@ -31,9 +32,8 @@ public class AuthAdminController {
|
||||
private final AuthAdminService authAdminService;
|
||||
|
||||
@PostMapping("/roles/{roleCode}/enable")
|
||||
@Operation(summary = "启用角色", description = "仅允许 SUPER_ADMIN FULL 会话启用目标角色。")
|
||||
@RequireRole("SUPER_ADMIN")
|
||||
@RequireAuthLevel("FULL")
|
||||
@Operation(summary = "启用角色", description = "仅允许 KEY_ADMIN FULL 会话启用目标角色。")
|
||||
@RequireInternalAuth(role = RoleCode.SUPER_ADMIN, authLevel = AuthLevel.FULL)
|
||||
public ApiResponse<Void> enableRole(@PathVariable("roleCode") String roleCode, HttpServletRequest request) {
|
||||
authAdminService.enableRole(
|
||||
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
|
||||
@@ -44,9 +44,8 @@ public class AuthAdminController {
|
||||
}
|
||||
|
||||
@PostMapping("/roles/{roleCode}/reset-password")
|
||||
@Operation(summary = "重置角色密码", description = "仅允许 SUPER_ADMIN FULL 会话重置目标角色密码。")
|
||||
@RequireRole("SUPER_ADMIN")
|
||||
@RequireAuthLevel("FULL")
|
||||
@Operation(summary = "重置角色密码", description = "仅允许 KEY_ADMIN FULL 会话重置目标角色密码。")
|
||||
@RequireInternalAuth(role = RoleCode.SUPER_ADMIN, authLevel = AuthLevel.FULL)
|
||||
public ApiResponse<Void> resetPassword(@PathVariable("roleCode") String roleCode, HttpServletRequest request) {
|
||||
authAdminService.resetPassword(
|
||||
(String) request.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
|
||||
@@ -57,9 +56,8 @@ public class AuthAdminController {
|
||||
}
|
||||
|
||||
@PostMapping("/roles/{roleCode}/ukeys/bind")
|
||||
@Operation(summary = "绑定角色 UKey", description = "仅允许 SUPER_ADMIN FULL 会话登记目标角色的 UKey 绑定信息。")
|
||||
@RequireRole("SUPER_ADMIN")
|
||||
@RequireAuthLevel("FULL")
|
||||
@Operation(summary = "绑定角色 UKey", description = "仅允许 KEY_ADMIN FULL 会话登记目标角色的 UKey 绑定信息。")
|
||||
@RequireInternalAuth(role = RoleCode.SUPER_ADMIN, authLevel = AuthLevel.FULL)
|
||||
public ApiResponse<Void> bindUkey(
|
||||
@PathVariable("roleCode") String roleCode,
|
||||
@Valid @RequestBody UkeyBindRequest request,
|
||||
@@ -69,11 +67,9 @@ public class AuthAdminController {
|
||||
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_ROLE_CODE),
|
||||
(String) httpRequest.getAttribute(InternalApiAuthInterceptor.ATTR_AUTH_LEVEL),
|
||||
roleCode,
|
||||
request.getSlotNo(),
|
||||
request.getUid(),
|
||||
request.getUkeySerial(),
|
||||
request.getPubKey(),
|
||||
request.getUid(),
|
||||
request.getRid(),
|
||||
request.getIssuerSignature()
|
||||
);
|
||||
return ApiResponse.success();
|
||||
@@ -81,8 +77,7 @@ public class AuthAdminController {
|
||||
|
||||
@PostMapping("/roles/{roleCode}/ukeys/issue-sign")
|
||||
@Operation(summary = "生成 UKey 发行签名", description = "按旧绑定流程为目标角色 UKey 材料生成发行签名。")
|
||||
// @RequireRole("SUPER_ADMIN")
|
||||
@RequireAuthLevel("FULL")
|
||||
@RequireInternalAuth(role = RoleCode.SUPER_ADMIN, authLevel = AuthLevel.LIMITED)
|
||||
public ApiResponse<UKeySignResult> issueUkeyBindingSign(
|
||||
@PathVariable("roleCode") String roleCode,
|
||||
@RequestBody UKeySignDTO request,
|
||||
|
||||
@@ -11,9 +11,11 @@ public class LoginRequest {
|
||||
@Schema(description = "角色编码", example = "KEY_ADMIN")
|
||||
private String roleCode;
|
||||
|
||||
@NotBlank(message = "password is required")
|
||||
@Schema(description = "登录密码", example = "P@ssw0rd")
|
||||
private String password;
|
||||
@Schema(description = "参与角色口令校验的账号列表")
|
||||
private List<PasswordLoginAccountRequest> accounts;
|
||||
|
||||
@Schema(description = "角色口令")
|
||||
private String rolePassword;
|
||||
|
||||
@Schema(description = "UKey 序列号列表,完整登录时需传入角色要求数量的序列号")
|
||||
private List<@NotBlank(message = "ukey serial must not be blank") String> ukeySerials;
|
||||
@@ -26,12 +28,20 @@ public class LoginRequest {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
public List<PasswordLoginAccountRequest> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
public void setAccounts(List<PasswordLoginAccountRequest> accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
public String getRolePassword() {
|
||||
return rolePassword;
|
||||
}
|
||||
|
||||
public void setRolePassword(String rolePassword) {
|
||||
this.rolePassword = rolePassword;
|
||||
}
|
||||
|
||||
public List<String> getUkeySerials() {
|
||||
|
||||
@@ -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 PasswordLoginAccountRequest {
|
||||
|
||||
@NotBlank(message = "username is required")
|
||||
@Schema(description = "账号名", example = "super-admin-01")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "password is required")
|
||||
@Schema(description = "账号口令", example = "12345678")
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
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 = "口令登录请求")
|
||||
public class PasswordLoginRequest {
|
||||
@@ -13,9 +16,10 @@ public class PasswordLoginRequest {
|
||||
@Schema(description = "角色编码", example = "AUDIT_ADMIN")
|
||||
private String roleCode;
|
||||
|
||||
@NotBlank(message = "password is required")
|
||||
@Schema(description = "登录口令", example = "12345678")
|
||||
private String password;
|
||||
@Valid
|
||||
@NotEmpty(message = "accounts is required")
|
||||
@Schema(description = "参与本次角色口令校验的账号列表")
|
||||
private List<PasswordLoginAccountRequest> accounts;
|
||||
|
||||
@NotBlank(message = "captchaCode is required")
|
||||
@Schema(description = "图形验证码", example = "ABCD")
|
||||
@@ -33,12 +37,12 @@ public class PasswordLoginRequest {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
public List<PasswordLoginAccountRequest> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
public void setAccounts(List<PasswordLoginAccountRequest> accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
public String getCaptchaCode() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
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;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
@Schema(description = "UKey 绑定请求")
|
||||
public class UkeyBindRequest {
|
||||
|
||||
@NotNull(message = "slotNo is required")
|
||||
@Schema(description = "角色 UKey 槽位号", example = "1")
|
||||
private Integer slotNo;
|
||||
@NotNull(message = "uid is required")
|
||||
@Schema(description = "角色内固定席位编号", example = "1")
|
||||
private Integer uid;
|
||||
|
||||
@NotBlank(message = "ukeySerial is required")
|
||||
@Schema(description = "UKey 序列号", example = "UK-001")
|
||||
@@ -19,24 +19,16 @@ public class UkeyBindRequest {
|
||||
@Schema(description = "UKey 公钥")
|
||||
private String pubKey;
|
||||
|
||||
@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 = "issuerSignature is required")
|
||||
@Schema(description = "认证公钥签名值")
|
||||
private String issuerSignature;
|
||||
|
||||
public Integer getSlotNo() {
|
||||
return slotNo;
|
||||
public Integer getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setSlotNo(Integer slotNo) {
|
||||
this.slotNo = slotNo;
|
||||
public void setUid(Integer uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getUkeySerial() {
|
||||
@@ -62,20 +54,4 @@ public class UkeyBindRequest {
|
||||
public void setIssuerSignature(String issuerSignature) {
|
||||
this.issuerSignature = issuerSignature;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ 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 UkeyLoginProof {
|
||||
@@ -9,11 +10,8 @@ public class UkeyLoginProof {
|
||||
@NotBlank(message = "pubKey is required")
|
||||
private String pubKey;
|
||||
|
||||
@NotBlank(message = "uid is required")
|
||||
private String uid;
|
||||
|
||||
@NotBlank(message = "rid is required")
|
||||
private String rid;
|
||||
@NotNull(message = "uid is required")
|
||||
private Integer uid;
|
||||
|
||||
/**
|
||||
* 对应旧系统下发的 rb,命名改为更明确的服务端随机数。
|
||||
@@ -38,22 +36,14 @@ public class UkeyLoginProof {
|
||||
this.pubKey = pubKey;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
public Integer getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
public void setUid(Integer uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getRid() {
|
||||
return rid;
|
||||
}
|
||||
|
||||
public void setRid(String rid) {
|
||||
this.rid = rid;
|
||||
}
|
||||
|
||||
public String getServerRandom() {
|
||||
return serverRandom;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ public class UkeyLoginRequest {
|
||||
@Schema(description = "角色编码", example = "KEY_ADMIN")
|
||||
private String roleCode;
|
||||
|
||||
@NotBlank(message = "password is required")
|
||||
@NotBlank(message = "rolePassword is required")
|
||||
@Schema(description = "角色口令", example = "12345678")
|
||||
private String password;
|
||||
private String rolePassword;
|
||||
|
||||
@Valid
|
||||
@NotEmpty(message = "ukeyProofs is required")
|
||||
@@ -30,12 +30,12 @@ public class UkeyLoginRequest {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
public String getRolePassword() {
|
||||
return rolePassword;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
public void setRolePassword(String rolePassword) {
|
||||
this.rolePassword = rolePassword;
|
||||
}
|
||||
|
||||
public List<UkeyLoginProof> getUkeyProofs() {
|
||||
|
||||
@@ -15,6 +15,10 @@ public class AuthSessionEntity extends BaseEntity {
|
||||
* 当前会话所属角色编码。
|
||||
*/
|
||||
private String roleCode;
|
||||
/**
|
||||
* 本次角色会话在后端侧记录的认证账号列表。
|
||||
*/
|
||||
private String authenticatedUsersJson;
|
||||
/**
|
||||
* 当前会话的认证方式,区分口令登录和 UKey 登录。
|
||||
*/
|
||||
@@ -44,6 +48,14 @@ public class AuthSessionEntity extends BaseEntity {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getAuthenticatedUsersJson() {
|
||||
return authenticatedUsersJson;
|
||||
}
|
||||
|
||||
public void setAuthenticatedUsersJson(String authenticatedUsersJson) {
|
||||
this.authenticatedUsersJson = authenticatedUsersJson;
|
||||
}
|
||||
|
||||
public String getAuthMethod() {
|
||||
return authMethod;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
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_user_account")
|
||||
public class AuthUserAccountEntity extends BaseEntity {
|
||||
|
||||
private String username;
|
||||
private String displayName;
|
||||
private String roleCode;
|
||||
private String passwordHash;
|
||||
private String passwordSalt;
|
||||
private String status;
|
||||
private Integer failedCount;
|
||||
private LocalDateTime lockedUntil;
|
||||
private LocalDateTime lastLoginAt;
|
||||
private LocalDateTime lastActiveAt;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getRoleCode() {
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
public void setRoleCode(String roleCode) {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
@@ -12,17 +12,9 @@ public class RoleUkeyBindingEntity extends BaseEntity {
|
||||
*/
|
||||
private String roleCode;
|
||||
/**
|
||||
* 角色下的 UKey 槽位,从 1 开始,和旧系统卡位模型保持一致。
|
||||
* 角色内固定席位编号,从 1 开始。
|
||||
*/
|
||||
private Integer slotNo;
|
||||
/**
|
||||
* 旧系统 auth 文件中的 uid,登录时要参与认证匹配。
|
||||
*/
|
||||
private String uid;
|
||||
/**
|
||||
* 旧系统 auth 文件中的 rid,登录时要参与角色槽位校验。
|
||||
*/
|
||||
private String rid;
|
||||
private Integer uid;
|
||||
private String ukeySerial;
|
||||
private String ukeyPubkey;
|
||||
private String issuerSign;
|
||||
@@ -38,30 +30,14 @@ public class RoleUkeyBindingEntity extends BaseEntity {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public Integer getSlotNo() {
|
||||
return slotNo;
|
||||
}
|
||||
|
||||
public void setSlotNo(Integer slotNo) {
|
||||
this.slotNo = slotNo;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
public Integer getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
public void setUid(Integer uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getRid() {
|
||||
return rid;
|
||||
}
|
||||
|
||||
public void setRid(String rid) {
|
||||
this.rid = rid;
|
||||
}
|
||||
|
||||
public String getUkeySerial() {
|
||||
return ukeySerial;
|
||||
}
|
||||
|
||||
@@ -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.AuthUserAccountEntity;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@Mapper
|
||||
public interface AuthUserAccountMapper extends BaseMapperX<AuthUserAccountEntity> {
|
||||
|
||||
AuthUserAccountEntity selectByUsername(@Param("username") String username);
|
||||
|
||||
List<AuthUserAccountEntity> selectByRoleCode(@Param("roleCode") String roleCode);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import org.apache.ibatis.annotations.Param;
|
||||
@Mapper
|
||||
public interface RoleUkeyBindingMapper extends BaseMapperX<RoleUkeyBindingEntity> {
|
||||
|
||||
RoleUkeyBindingEntity selectActiveByRoleCodeAndSlotNo(@Param("roleCode") String roleCode, @Param("slotNo") Integer slotNo);
|
||||
RoleUkeyBindingEntity selectActiveByRoleCodeAndUid(@Param("roleCode") String roleCode, @Param("uid") Integer uid);
|
||||
|
||||
List<RoleUkeyBindingEntity> selectActiveByRoleCode(@Param("roleCode") String roleCode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cisd.tms.modules.auth.repository;
|
||||
|
||||
import com.cisd.tms.modules.auth.entity.AuthUserAccountEntity;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface AuthUserAccountRepository {
|
||||
|
||||
Optional<AuthUserAccountEntity> findByUsername(String username);
|
||||
|
||||
List<AuthUserAccountEntity> findByRoleCode(String roleCode);
|
||||
|
||||
void save(AuthUserAccountEntity entity);
|
||||
|
||||
void update(AuthUserAccountEntity entity);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import java.util.Optional;
|
||||
|
||||
public interface RoleUkeyBindingRepository {
|
||||
|
||||
Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndSlotNo(String roleCode, Integer slotNo);
|
||||
Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndUid(String roleCode, Integer uid);
|
||||
|
||||
List<RoleUkeyBindingEntity> findActiveByRoleCode(String roleCode);
|
||||
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.cisd.tms.modules.auth.repository.impl;
|
||||
|
||||
import com.cisd.tms.modules.auth.entity.AuthUserAccountEntity;
|
||||
import com.cisd.tms.modules.auth.mapper.AuthUserAccountMapper;
|
||||
import com.cisd.tms.modules.auth.repository.AuthUserAccountRepository;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class AuthUserAccountRepositoryImpl implements AuthUserAccountRepository {
|
||||
|
||||
private final AuthUserAccountMapper authUserAccountMapper;
|
||||
|
||||
public AuthUserAccountRepositoryImpl(AuthUserAccountMapper authUserAccountMapper) {
|
||||
this.authUserAccountMapper = authUserAccountMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AuthUserAccountEntity> findByUsername(String username) {
|
||||
return Optional.ofNullable(authUserAccountMapper.selectByUsername(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthUserAccountEntity> findByRoleCode(String roleCode) {
|
||||
return authUserAccountMapper.selectByRoleCode(roleCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(AuthUserAccountEntity entity) {
|
||||
authUserAccountMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AuthUserAccountEntity entity) {
|
||||
authUserAccountMapper.updateById(entity);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -17,8 +17,8 @@ public class RoleUkeyBindingRepositoryImpl implements RoleUkeyBindingRepository
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndSlotNo(String roleCode, Integer slotNo) {
|
||||
return Optional.ofNullable(roleUkeyBindingMapper.selectActiveByRoleCodeAndSlotNo(roleCode, slotNo));
|
||||
public Optional<RoleUkeyBindingEntity> findActiveByRoleCodeAndUid(String roleCode, Integer uid) {
|
||||
return Optional.ofNullable(roleUkeyBindingMapper.selectActiveByRoleCodeAndUid(roleCode, uid));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-2
@@ -1,5 +1,7 @@
|
||||
package com.cisd.tms.modules.auth.security;
|
||||
|
||||
import com.cisd.tms.modules.auth.enums.AuthLevel;
|
||||
import com.cisd.tms.modules.auth.enums.RoleCode;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -7,7 +9,9 @@ import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface RequireAuthLevel {
|
||||
public @interface RequireInternalAuth {
|
||||
|
||||
String value();
|
||||
RoleCode role();
|
||||
|
||||
AuthLevel authLevel();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
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();
|
||||
}
|
||||
@@ -13,11 +13,9 @@ public interface AuthAdminService {
|
||||
String operatorRoleCode,
|
||||
String operatorAuthLevel,
|
||||
String targetRoleCode,
|
||||
Integer slotNo,
|
||||
Integer uid,
|
||||
String ukeySerial,
|
||||
String ukeyPubkey,
|
||||
String uid,
|
||||
String rid,
|
||||
String issuerSign
|
||||
);
|
||||
|
||||
@@ -25,11 +23,9 @@ public interface AuthAdminService {
|
||||
String operatorRoleCode,
|
||||
String operatorAuthLevel,
|
||||
String targetRoleCode,
|
||||
Integer slotNo,
|
||||
Integer uid,
|
||||
String ukeySerial,
|
||||
String ukeyPubkey,
|
||||
String uid,
|
||||
String rid,
|
||||
String issuerSign
|
||||
);
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@ package com.cisd.tms.modules.auth.service.impl;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.common.exception.BizException;
|
||||
import com.cisd.tms.common.util.TraceIdUtil;
|
||||
import com.cisd.tms.modules.auth.entity.AuthUserAccountEntity;
|
||||
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.AuthUserAccountRepository;
|
||||
import com.cisd.tms.modules.auth.repository.RoleAccountRepository;
|
||||
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
|
||||
import com.cisd.tms.modules.auth.service.AuthAdminService;
|
||||
@@ -35,6 +36,7 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
static final String DEFAULT_PASSWORD = "12345678";
|
||||
|
||||
private final RoleAccountRepository roleAccountRepository;
|
||||
private final AuthUserAccountRepository authUserAccountRepository;
|
||||
private final RoleUkeyBindingRepository roleUkeyBindingRepository;
|
||||
private final PasswordHasher passwordHasher;
|
||||
private final LmkService lmkService;
|
||||
@@ -44,7 +46,6 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
|
||||
@Override
|
||||
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);
|
||||
@@ -55,16 +56,31 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
|
||||
@Override
|
||||
public void resetPassword(String operatorRoleCode, String operatorAuthLevel, String targetRoleCode) {
|
||||
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
|
||||
RoleAccountEntity target = loadRole(targetRoleCode);
|
||||
String newSalt = passwordSaltGenerator.nextSalt();
|
||||
target.setPasswordSalt(newSalt);
|
||||
target.setPasswordHash(passwordHasher.hash(DEFAULT_PASSWORD, newSalt));
|
||||
String roleSalt = passwordSaltGenerator.nextSalt();
|
||||
target.setPasswordSalt(roleSalt);
|
||||
target.setPasswordHash(passwordHasher.hash(DEFAULT_PASSWORD, roleSalt));
|
||||
target.setStatus(RoleAccountStatus.ACTIVE.name());
|
||||
target.setNeedChangePassword(Boolean.TRUE);
|
||||
target.setFailedCount(0);
|
||||
target.setLockedUntil(null);
|
||||
roleAccountRepository.update(target);
|
||||
|
||||
List<AuthUserAccountEntity> accounts = authUserAccountRepository.findByRoleCode(targetRoleCode);
|
||||
if (accounts.isEmpty()) {
|
||||
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "target role user accounts not found");
|
||||
}
|
||||
for (AuthUserAccountEntity account : accounts) {
|
||||
String newSalt = passwordSaltGenerator.nextSalt();
|
||||
account.setPasswordSalt(newSalt);
|
||||
account.setPasswordHash(passwordHasher.hash(DEFAULT_PASSWORD, newSalt));
|
||||
account.setStatus(RoleAccountStatus.ACTIVE.name());
|
||||
account.setFailedCount(0);
|
||||
account.setLockedUntil(null);
|
||||
account.setLastActiveAt(null);
|
||||
account.setLastLoginAt(null);
|
||||
authUserAccountRepository.update(account);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,33 +88,30 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
String operatorRoleCode,
|
||||
String operatorAuthLevel,
|
||||
String targetRoleCode,
|
||||
Integer slotNo,
|
||||
Integer uid,
|
||||
String ukeySerial,
|
||||
String ukeyPubkey,
|
||||
String uid,
|
||||
String rid,
|
||||
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");
|
||||
if (uid == null || uid < 1 || uid > targetRole.getRequiredUkeyCount()) {
|
||||
throw new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "uid exceeds role ukey requirement");
|
||||
}
|
||||
|
||||
RoleUkeyBindingEntity binding = roleUkeyBindingRepository
|
||||
.findActiveByRoleCodeAndSlotNo(targetRoleCode, slotNo)
|
||||
.findActiveByRoleCodeAndUid(targetRoleCode, uid)
|
||||
.orElseGet(RoleUkeyBindingEntity::new);
|
||||
if (binding.getId() == null) {
|
||||
binding.setId((long) Math.abs(Objects.hash(targetRoleCode, slotNo, ukeySerial, TraceIdUtil.newTraceId())));
|
||||
binding.setId((long) Math.abs(Objects.hash(targetRoleCode, uid, ukeySerial, TraceIdUtil.newTraceId())));
|
||||
binding.setRoleCode(targetRoleCode);
|
||||
binding.setSlotNo(slotNo);
|
||||
binding.setUid(uid);
|
||||
binding.setStatus("ACTIVE");
|
||||
applyBinding(binding, ukeySerial, ukeyPubkey, uid, rid, issuerSign);
|
||||
applyBinding(binding, ukeySerial, ukeyPubkey, issuerSign);
|
||||
roleUkeyBindingRepository.save(binding);
|
||||
return;
|
||||
}
|
||||
|
||||
applyBinding(binding, ukeySerial, ukeyPubkey, uid, rid, issuerSign);
|
||||
applyBinding(binding, ukeySerial, ukeyPubkey, issuerSign);
|
||||
roleUkeyBindingRepository.update(binding);
|
||||
}
|
||||
|
||||
@@ -107,17 +120,14 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
String operatorRoleCode,
|
||||
String operatorAuthLevel,
|
||||
String targetRoleCode,
|
||||
Integer slotNo,
|
||||
Integer uid,
|
||||
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, uid, rid, issuerSign);
|
||||
verifyIssuerSignature(targetRoleCode, ukeyPubkey, uid, issuerSign);
|
||||
bindUkey(operatorRoleCode, operatorAuthLevel, targetRoleCode, uid, ukeySerial, ukeyPubkey, issuerSign);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,7 +137,6 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
String targetRoleCode,
|
||||
UKeySignDTO request
|
||||
) {
|
||||
requireKeyAdminFull(operatorRoleCode, operatorAuthLevel);
|
||||
RoleCode targetRole = resolveRoleCode(targetRoleCode);
|
||||
String authKeyPair = lmkService.exportIkPublicKeyHex();
|
||||
|
||||
@@ -135,12 +144,11 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
dto.setPubKey(request.getPubKey());
|
||||
dto.setRole(targetRole.getCode());
|
||||
dto.setUid(request.getUid());
|
||||
dto.setRid(request.getRid());
|
||||
|
||||
String signValue = lmkService.signIk(toIssuePayload(dto, authKeyPair));
|
||||
MasterKeyBackupPacket backupPacket = null;
|
||||
if (RoleCode.SUPER_ADMIN == targetRole) {
|
||||
backupPacket = lmkService.buildBackupPacket(Integer.parseInt(request.getUid()));
|
||||
backupPacket = lmkService.buildBackupPacket(request.getUid());
|
||||
}
|
||||
return UKeySignResult.builder()
|
||||
.sign(signValue)
|
||||
@@ -152,26 +160,16 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
RoleUkeyBindingEntity binding,
|
||||
String ukeySerial,
|
||||
String ukeyPubkey,
|
||||
String uid,
|
||||
String rid,
|
||||
String issuerSign
|
||||
) {
|
||||
binding.setUkeySerial(ukeySerial);
|
||||
binding.setUkeyPubkey(ukeyPubkey);
|
||||
binding.setUid(uid);
|
||||
binding.setRid(rid);
|
||||
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)
|
||||
@@ -189,13 +187,12 @@ public class AuthAdminServiceImpl implements AuthAdminService {
|
||||
return LocalDateTime.ofInstant(clock.instant(), ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
private void verifyIssuerSignature(String targetRoleCode, String ukeyPubkey, String uid, String rid, String issuerSign) {
|
||||
private void verifyIssuerSignature(String targetRoleCode, String ukeyPubkey, Integer uid, String issuerSign) {
|
||||
try {
|
||||
UKeySignDTO dto = new UKeySignDTO();
|
||||
dto.setPubKey(ukeyPubkey);
|
||||
dto.setRole(resolveRoleCode(targetRoleCode).getCode());
|
||||
dto.setUid(uid);
|
||||
dto.setRid(rid);
|
||||
String authKeyPair = lmkService.exportIkPublicKeyHex();
|
||||
lmkService.verifyIk(toIssuePayload(dto, authKeyPair), issuerSign);
|
||||
} catch (BizException ex) {
|
||||
|
||||
@@ -6,12 +6,14 @@ import com.cisd.tms.modules.auth.dto.CaptchaResponse;
|
||||
import com.cisd.tms.modules.auth.dto.CurrentUserResponse;
|
||||
import com.cisd.tms.modules.auth.dto.LoginRequest;
|
||||
import com.cisd.tms.modules.auth.dto.LoginResponse;
|
||||
import com.cisd.tms.modules.auth.dto.PasswordLoginAccountRequest;
|
||||
import com.cisd.tms.modules.auth.dto.PasswordLoginRequest;
|
||||
import com.cisd.tms.modules.auth.dto.UkeyLoginProof;
|
||||
import com.cisd.tms.modules.auth.dto.UkeyLoginRandomRequest;
|
||||
import com.cisd.tms.modules.auth.dto.UkeyLoginRandomResponse;
|
||||
import com.cisd.tms.modules.auth.dto.UkeyLoginRequest;
|
||||
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
|
||||
import com.cisd.tms.modules.auth.entity.AuthUserAccountEntity;
|
||||
import com.cisd.tms.modules.auth.entity.AuthUserEntity;
|
||||
import com.cisd.tms.modules.auth.entity.RoleAccountEntity;
|
||||
import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity;
|
||||
@@ -20,10 +22,18 @@ import com.cisd.tms.modules.auth.enums.AuthMethod;
|
||||
import com.cisd.tms.modules.auth.enums.RoleAccountStatus;
|
||||
import com.cisd.tms.modules.auth.enums.RoleCode;
|
||||
import com.cisd.tms.modules.auth.repository.AuthSessionRepository;
|
||||
import com.cisd.tms.modules.auth.repository.AuthUserAccountRepository;
|
||||
import com.cisd.tms.modules.auth.repository.AuthUserRepository;
|
||||
import com.cisd.tms.modules.auth.repository.RoleAccountRepository;
|
||||
import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository;
|
||||
import com.cisd.tms.modules.auth.service.*;
|
||||
import com.cisd.tms.modules.auth.service.AuthPolicyService;
|
||||
import com.cisd.tms.modules.auth.service.AuthService;
|
||||
import com.cisd.tms.modules.auth.service.CaptchaService;
|
||||
import com.cisd.tms.modules.auth.service.CompatUkeyVerifier;
|
||||
import com.cisd.tms.modules.auth.service.PasswordHasher;
|
||||
import com.cisd.tms.modules.auth.service.PasswordSaltGenerator;
|
||||
import com.cisd.tms.modules.auth.service.SessionTokenGenerator;
|
||||
import com.cisd.tms.modules.auth.service.UkeyLoginRandomService;
|
||||
import com.cisd.tms.modules.mk.dto.UKeySignDTO;
|
||||
import com.cisd.tms.modules.mk.dto.UKeySignEntity;
|
||||
import com.cisd.tms.modules.mk.enums.MasterKeyStatus;
|
||||
@@ -34,6 +44,7 @@ import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -51,6 +62,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
private final RoleAccountRepository roleAccountRepository;
|
||||
private final AuthUserRepository authUserRepository;
|
||||
private final AuthUserAccountRepository authUserAccountRepository;
|
||||
private final AuthSessionRepository authSessionRepository;
|
||||
private final RoleUkeyBindingRepository roleUkeyBindingRepository;
|
||||
private final PasswordHasher passwordHasher;
|
||||
@@ -70,14 +82,22 @@ public class AuthServiceImpl implements AuthService {
|
||||
.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);
|
||||
AuthMethod authMethod = resolveAuthMethod(request.getUkeySerials());
|
||||
List<AuthUserAccountEntity> validatedAccounts = new ArrayList<>();
|
||||
if (AuthMethod.PASSWORD == authMethod) {
|
||||
validatedAccounts = validateRoleAccounts(roleAccount, request.getAccounts());
|
||||
resetValidatedAccounts(validatedAccounts);
|
||||
} else {
|
||||
validateRolePassword(roleAccount, request.getRolePassword());
|
||||
resetRoleFailureState(roleAccount);
|
||||
}
|
||||
AuthLevel authLevel = resolveAuthLevel(roleAccount, request.getUkeySerials());
|
||||
AuthSessionEntity session = buildSession(roleAccount.getRoleCode(), authMethod, authLevel);
|
||||
AuthSessionEntity session = buildSession(
|
||||
roleAccount.getRoleCode(),
|
||||
authMethod,
|
||||
authLevel,
|
||||
validatedAccounts.isEmpty() ? null : validatedAccounts.stream().map(AuthUserAccountEntity::getUsername).toList()
|
||||
);
|
||||
authSessionRepository.save(session);
|
||||
|
||||
LoginResponse response = new LoginResponse();
|
||||
@@ -85,7 +105,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
response.setAuthLevel(authLevel.name());
|
||||
response.setToken(session.getSessionToken());
|
||||
response.setExpiresAt(OffsetDateTime.of(session.getExpiresAt(), ZoneOffset.UTC).toString());
|
||||
response.setNeedChangePassword(Boolean.TRUE.equals(roleAccount.getNeedChangePassword()));
|
||||
response.setNeedChangePassword(needsPasswordChange(roleAccount));
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -95,7 +115,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
captchaService.verify(request.getCaptchaId(), request.getCaptchaCode());
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setRoleCode(request.getRoleCode());
|
||||
loginRequest.setPassword(request.getPassword());
|
||||
loginRequest.setAccounts(request.getAccounts());
|
||||
return login(loginRequest);
|
||||
}
|
||||
|
||||
@@ -114,12 +134,12 @@ public class AuthServiceImpl implements AuthService {
|
||||
RoleCode roleCode = RoleCode.valueOf(request.getRoleCode());
|
||||
List<RoleUkeyBindingEntity> activeBindings = roleUkeyBindingRepository.findActiveByRoleCode(roleCode.getCode());
|
||||
validateUkeyCount(roleCode, activeBindings, request.getUkeyProofs());
|
||||
Map<String, RoleUkeyBindingEntity> bindingsByPubKey = activeBindings.stream()
|
||||
.collect(Collectors.toMap(RoleUkeyBindingEntity::getUkeyPubkey, item -> item, (left, right) -> left, java.util.LinkedHashMap::new));
|
||||
Set<String> requestPubKeys = request.getUkeyProofs().stream()
|
||||
.map(UkeyLoginProof::getPubKey)
|
||||
Map<Integer, RoleUkeyBindingEntity> bindingsByUid = activeBindings.stream()
|
||||
.collect(Collectors.toMap(RoleUkeyBindingEntity::getUid, item -> item, (left, right) -> left, java.util.LinkedHashMap::new));
|
||||
Set<Integer> requestUids = request.getUkeyProofs().stream()
|
||||
.map(UkeyLoginProof::getUid)
|
||||
.collect(Collectors.toSet());
|
||||
if (requestPubKeys.size() != request.getUkeyProofs().size() || !bindingsByPubKey.keySet().containsAll(requestPubKeys)) {
|
||||
if (requestUids.size() != request.getUkeyProofs().size() || !bindingsByUid.keySet().containsAll(requestUids)) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey auth info does not match bound role");
|
||||
}
|
||||
ukeyLoginRandomService.assertIssued(
|
||||
@@ -127,16 +147,19 @@ public class AuthServiceImpl implements AuthService {
|
||||
request.getUkeyProofs().stream().map(UkeyLoginProof::getServerRandom).toList()
|
||||
);
|
||||
String authKeyPair = lmkService.exportIkPublicKeyHex();
|
||||
List<String> matchedSerials = new java.util.ArrayList<>();
|
||||
List<String> matchedSerials = new ArrayList<>();
|
||||
for (UkeyLoginProof proof : request.getUkeyProofs()) {
|
||||
RoleUkeyBindingEntity binding = bindingsByPubKey.get(proof.getPubKey());
|
||||
RoleUkeyBindingEntity binding = bindingsByUid.get(proof.getUid());
|
||||
if (binding == null || !binding.getUkeyPubkey().equals(proof.getPubKey())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey auth info does not match bound role");
|
||||
}
|
||||
compatUkeyVerifier.verifyIssuedBinding(buildIssuePayload(request.getRoleCode(), proof, authKeyPair), proof.getIssueSignature());
|
||||
compatUkeyVerifier.verifyLoginSignature(proof.getPubKey(), proof.getLoginPayload(), proof.getLoginSignature());
|
||||
matchedSerials.add(binding.getUkeySerial());
|
||||
}
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setRoleCode(request.getRoleCode());
|
||||
loginRequest.setPassword(request.getPassword());
|
||||
loginRequest.setRolePassword(request.getRolePassword());
|
||||
loginRequest.setUkeySerials(matchedSerials);
|
||||
return login(loginRequest);
|
||||
}
|
||||
@@ -164,23 +187,24 @@ public class AuthServiceImpl implements AuthService {
|
||||
if (session != null) {
|
||||
response.setAuthLevel(session.getAuthLevel());
|
||||
}
|
||||
response.setNeedChangePassword(Boolean.TRUE.equals(roleAccount.getNeedChangePassword()));
|
||||
response.setNeedChangePassword(needsPasswordChange(roleAccount));
|
||||
return response;
|
||||
}
|
||||
|
||||
AuthUserEntity entity = authUserRepository.findByUsername(normalized).orElse(null);
|
||||
|
||||
CurrentUserResponse response = new CurrentUserResponse();
|
||||
if (entity == null) {
|
||||
response.setUsername(normalized);
|
||||
response.setDisplayName("TMS Administrator");
|
||||
response.setRole("ADMIN");
|
||||
response.setNeedChangePassword(Boolean.FALSE);
|
||||
return response;
|
||||
}
|
||||
|
||||
response.setUsername(entity.getUsername());
|
||||
response.setDisplayName(entity.getDisplayName());
|
||||
response.setRole(entity.getRole());
|
||||
response.setNeedChangePassword(Boolean.FALSE);
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -197,34 +221,107 @@ public class AuthServiceImpl implements AuthService {
|
||||
AuthSessionEntity session = requireActiveSession(sessionToken);
|
||||
RoleAccountEntity roleAccount = roleAccountRepository.findByRoleCode(session.getRoleCode())
|
||||
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role account not found"));
|
||||
validateRoleStatus(roleAccount);
|
||||
if (!passwordHasher.matches(currentPassword, roleAccount.getPasswordSalt(), roleAccount.getPasswordHash())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "current password is incorrect");
|
||||
onRolePasswordFailed(roleAccount);
|
||||
}
|
||||
|
||||
String newSalt = passwordSaltGenerator.nextSalt();
|
||||
roleAccount.setPasswordSalt(newSalt);
|
||||
roleAccount.setPasswordHash(passwordHasher.hash(newPassword, newSalt));
|
||||
String salt = passwordSaltGenerator.nextSalt();
|
||||
LocalDateTime current = now();
|
||||
roleAccount.setPasswordSalt(salt);
|
||||
roleAccount.setPasswordHash(passwordHasher.hash(newPassword, salt));
|
||||
roleAccount.setNeedChangePassword(Boolean.FALSE);
|
||||
roleAccount.setFailedCount(0);
|
||||
roleAccount.setLockedUntil(null);
|
||||
roleAccount.setStatus(RoleAccountStatus.ACTIVE.name());
|
||||
roleAccount.setLastActiveAt(current);
|
||||
roleAccountRepository.update(roleAccount);
|
||||
|
||||
session.setLastActiveAt(current);
|
||||
session.setExpiresAt(current.plusMinutes(IDLE_TIMEOUT_MINUTES));
|
||||
authSessionRepository.update(session);
|
||||
}
|
||||
|
||||
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)) {
|
||||
if (RoleAccountStatus.LOCKED.name().equals(roleAccount.getStatus())
|
||||
&& (roleAccount.getLockedUntil() == null || roleAccount.getLockedUntil().isAfter(now()))) {
|
||||
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 validateRolePassword(RoleAccountEntity roleAccount, String rolePassword) {
|
||||
if (rolePassword == null || rolePassword.isBlank()) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "role password is required");
|
||||
}
|
||||
if (!passwordHasher.matches(rolePassword, roleAccount.getPasswordSalt(), roleAccount.getPasswordHash())) {
|
||||
onRolePasswordFailed(roleAccount);
|
||||
}
|
||||
}
|
||||
|
||||
private void onPasswordFailed(RoleAccountEntity roleAccount) {
|
||||
private List<AuthUserAccountEntity> validateRoleAccounts(
|
||||
RoleAccountEntity roleAccount,
|
||||
List<PasswordLoginAccountRequest> accounts
|
||||
) {
|
||||
int expectedCount = requiredPasswordAccountCount(roleAccount.getRoleCode());
|
||||
if (accounts == null || accounts.size() != expectedCount) {
|
||||
throw new BizException(
|
||||
ErrorCode.UNAUTHORIZED.getCode(),
|
||||
roleAccount.getRoleCode() + " requires exactly " + expectedCount + " account passwords"
|
||||
);
|
||||
}
|
||||
|
||||
Set<String> uniqueUsernames = new LinkedHashSet<>();
|
||||
List<AuthUserAccountEntity> validatedAccounts = new ArrayList<>();
|
||||
for (PasswordLoginAccountRequest account : accounts) {
|
||||
if (!uniqueUsernames.add(account.getUsername())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "duplicate account username submitted");
|
||||
}
|
||||
AuthUserAccountEntity userAccount = authUserAccountRepository.findByUsername(account.getUsername())
|
||||
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "user account not found"));
|
||||
validateUserAccountRole(roleAccount.getRoleCode(), userAccount);
|
||||
validateUserAccountStatus(userAccount);
|
||||
if (!passwordHasher.matches(account.getPassword(), userAccount.getPasswordSalt(), userAccount.getPasswordHash())) {
|
||||
onPasswordFailed(userAccount);
|
||||
}
|
||||
validatedAccounts.add(userAccount);
|
||||
}
|
||||
return validatedAccounts;
|
||||
}
|
||||
|
||||
private void validateUserAccountRole(String expectedRoleCode, AuthUserAccountEntity userAccount) {
|
||||
if (!expectedRoleCode.equals(userAccount.getRoleCode())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "user account does not belong to target role");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateUserAccountStatus(AuthUserAccountEntity userAccount) {
|
||||
if (RoleAccountStatus.UNENABLED.name().equals(userAccount.getStatus())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "user account is not enabled");
|
||||
}
|
||||
if (RoleAccountStatus.LOCKED.name().equals(userAccount.getStatus())
|
||||
&& (userAccount.getLockedUntil() == null || userAccount.getLockedUntil().isAfter(now()))) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "user account is locked");
|
||||
}
|
||||
}
|
||||
|
||||
private void onPasswordFailed(AuthUserAccountEntity userAccount) {
|
||||
int failedCount = userAccount.getFailedCount() == null ? 0 : userAccount.getFailedCount();
|
||||
failedCount++;
|
||||
userAccount.setFailedCount(failedCount);
|
||||
if (failedCount >= MAX_FAILED_ATTEMPTS) {
|
||||
userAccount.setStatus(RoleAccountStatus.LOCKED.name());
|
||||
userAccount.setLockedUntil(now().plusMinutes(IDLE_TIMEOUT_MINUTES));
|
||||
authUserAccountRepository.update(userAccount);
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "user account is locked");
|
||||
}
|
||||
authUserAccountRepository.update(userAccount);
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "password is incorrect");
|
||||
}
|
||||
|
||||
private void onRolePasswordFailed(RoleAccountEntity roleAccount) {
|
||||
int failedCount = roleAccount.getFailedCount() == null ? 0 : roleAccount.getFailedCount();
|
||||
failedCount++;
|
||||
roleAccount.setFailedCount(failedCount);
|
||||
@@ -238,7 +335,19 @@ public class AuthServiceImpl implements AuthService {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "password is incorrect");
|
||||
}
|
||||
|
||||
private void resetFailureState(RoleAccountEntity roleAccount) {
|
||||
private void resetValidatedAccounts(List<AuthUserAccountEntity> validatedAccounts) {
|
||||
LocalDateTime current = now();
|
||||
for (AuthUserAccountEntity account : validatedAccounts) {
|
||||
account.setFailedCount(0);
|
||||
account.setLockedUntil(null);
|
||||
account.setStatus(RoleAccountStatus.ACTIVE.name());
|
||||
account.setLastLoginAt(current);
|
||||
account.setLastActiveAt(current);
|
||||
authUserAccountRepository.update(account);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetRoleFailureState(RoleAccountEntity roleAccount) {
|
||||
roleAccount.setFailedCount(0);
|
||||
roleAccount.setLockedUntil(null);
|
||||
roleAccount.setStatus(RoleAccountStatus.ACTIVE.name());
|
||||
@@ -247,6 +356,10 @@ public class AuthServiceImpl implements AuthService {
|
||||
roleAccountRepository.update(roleAccount);
|
||||
}
|
||||
|
||||
private int requiredPasswordAccountCount(String roleCode) {
|
||||
return RoleCode.valueOf(roleCode).getRequiredUkeyCount();
|
||||
}
|
||||
|
||||
private void ensureMasterKeyReady() {
|
||||
MasterKeyStatus.StatusDetail status = lmkService.getMasterKeyStatus();
|
||||
if (status == null || status.getCode() == MasterKeyStatus.ABNORMAL.getCode()) {
|
||||
@@ -264,18 +377,19 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
|
||||
Set<String> uniqueSerials = new LinkedHashSet<>(ukeySerials);
|
||||
if (uniqueSerials.size() != roleAccount.getRequiredUkeyCount()) {
|
||||
int requiredUkeyCount = authPolicyService.requiredUkeyCount(RoleCode.valueOf(roleAccount.getRoleCode()));
|
||||
if (uniqueSerials.size() != requiredUkeyCount) {
|
||||
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()) {
|
||||
if (bindings.size() != requiredUkeyCount) {
|
||||
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());
|
||||
.collect(Collectors.toSet());
|
||||
if (!boundSerials.containsAll(uniqueSerials)) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "ukey verification failed");
|
||||
}
|
||||
@@ -300,7 +414,6 @@ public class AuthServiceImpl implements AuthService {
|
||||
dto.setPubKey(proof.getPubKey());
|
||||
dto.setRole(RoleCode.valueOf(roleCode).getCode());
|
||||
dto.setUid(proof.getUid());
|
||||
dto.setRid(proof.getRid());
|
||||
try {
|
||||
return objectMapper.writeValueAsString(UKeySignEntity.getInstance(dto, authKeyPair));
|
||||
} catch (JsonProcessingException ex) {
|
||||
@@ -308,10 +421,16 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
private AuthSessionEntity buildSession(String roleCode, AuthMethod authMethod, AuthLevel authLevel) {
|
||||
private AuthSessionEntity buildSession(
|
||||
String roleCode,
|
||||
AuthMethod authMethod,
|
||||
AuthLevel authLevel,
|
||||
List<String> authenticatedUsers
|
||||
) {
|
||||
LocalDateTime issuedAt = now();
|
||||
AuthSessionEntity entity = new AuthSessionEntity();
|
||||
entity.setRoleCode(roleCode);
|
||||
entity.setAuthenticatedUsersJson(writeAuthenticatedUsers(authenticatedUsers));
|
||||
entity.setAuthMethod(authMethod.name());
|
||||
entity.setAuthLevel(authLevel.name());
|
||||
entity.setSessionToken(sessionTokenGenerator.nextToken());
|
||||
@@ -321,10 +440,25 @@ public class AuthServiceImpl implements AuthService {
|
||||
return entity;
|
||||
}
|
||||
|
||||
private String writeAuthenticatedUsers(List<String> authenticatedUsers) {
|
||||
if (authenticatedUsers == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.writeValueAsString(authenticatedUsers);
|
||||
} catch (JsonProcessingException ex) {
|
||||
throw new IllegalStateException("serialize authenticated users failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private LocalDateTime now() {
|
||||
return LocalDateTime.ofInstant(clock.instant(), ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
private boolean needsPasswordChange(RoleAccountEntity roleAccount) {
|
||||
return Boolean.TRUE.equals(roleAccount.getNeedChangePassword());
|
||||
}
|
||||
|
||||
private AuthSessionEntity requireActiveSession(String sessionToken) {
|
||||
AuthSessionEntity session = authSessionRepository.findBySessionToken(sessionToken)
|
||||
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "session not found"));
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.function.Supplier;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@@ -18,6 +19,7 @@ public class RunnerStallDetector {
|
||||
private final ResourceBackupProperties resourceBackupProperties;
|
||||
private final Supplier<LocalDateTime> nowSupplier;
|
||||
|
||||
@Autowired
|
||||
public RunnerStallDetector(
|
||||
ResourceRestoreTaskRepository resourceRestoreTaskRepository,
|
||||
ResourceRestoreStateFileStore resourceRestoreStateFileStore,
|
||||
|
||||
@@ -83,8 +83,8 @@ public class MasterKeyRestoreDTO {
|
||||
this.iDevPriKeyLen = iDevPriKeyLen;
|
||||
}
|
||||
|
||||
public Map<String,String> getComponents() {
|
||||
Map<String,String> componentMap = new HashMap<>();
|
||||
public Map<Integer,String> getComponents() {
|
||||
Map<Integer,String> componentMap = new HashMap<>();
|
||||
for(UKeySignVerifyDTO uKeySignVerifyDTO : uKeySignVerifyDTOList){
|
||||
if(null == uKeySignVerifyDTO.getKeyComponent()){
|
||||
throw new IllegalArgumentException("UKey无主密钥分量,UID:" + uKeySignVerifyDTO.getuKeySignDTO().getUid());
|
||||
|
||||
@@ -9,11 +9,6 @@ public class UKey {
|
||||
*/
|
||||
private String uid;
|
||||
|
||||
/**
|
||||
* 角色 ID
|
||||
*/
|
||||
private String rid;
|
||||
|
||||
/**
|
||||
* 设备公钥 HEX(32 字节 x + 32 字节 y)
|
||||
*/
|
||||
|
||||
@@ -18,13 +18,8 @@ public class UKeySignDTO {
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* UKey 中的认证信息
|
||||
* 角色内固定席位编号。
|
||||
*/
|
||||
private String uid;
|
||||
|
||||
/**
|
||||
* UKey 中的认证信息
|
||||
*/
|
||||
private String rid;
|
||||
private Integer uid;
|
||||
|
||||
}
|
||||
|
||||
@@ -25,11 +25,7 @@ public class UKeySignEntity {
|
||||
/**
|
||||
* 登录时传输
|
||||
*/
|
||||
private String uid;
|
||||
/**
|
||||
* 登录时传输
|
||||
*/
|
||||
private String rid;
|
||||
private Integer uid;
|
||||
|
||||
public static UKeySignEntity getInstance(UKeySignDTO uKeySignDTO,String authKeyPair){
|
||||
return UKeySignEntity.builder()
|
||||
@@ -37,7 +33,6 @@ public class UKeySignEntity {
|
||||
.authKeyPair(authKeyPair)
|
||||
.role(uKeySignDTO.getRole())
|
||||
.uid(uKeySignDTO.getUid())
|
||||
.rid(uKeySignDTO.getRid())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,9 +260,7 @@ CREATE TABLE IF NOT EXISTS tms_role_account (
|
||||
CREATE TABLE IF NOT EXISTS tms_role_ukey_binding (
|
||||
id BIGINT PRIMARY KEY,
|
||||
role_code VARCHAR(64) NOT NULL,
|
||||
slot_no INT NOT NULL,
|
||||
uid VARCHAR(64) NULL,
|
||||
rid VARCHAR(64) NULL,
|
||||
uid INT NOT NULL,
|
||||
ukey_serial VARCHAR(128) NOT NULL,
|
||||
ukey_pubkey TEXT NOT NULL,
|
||||
issuer_sign TEXT NULL,
|
||||
@@ -271,14 +269,33 @@ CREATE TABLE IF NOT EXISTS tms_role_ukey_binding (
|
||||
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),
|
||||
UNIQUE KEY uk_tms_role_ukey_binding_role_uid (role_code, uid),
|
||||
KEY idx_tms_role_ukey_binding_role_status (role_code, status)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tms_auth_user_account (
|
||||
id BIGINT PRIMARY KEY,
|
||||
username VARCHAR(64) NOT NULL,
|
||||
display_name VARCHAR(128) NOT NULL,
|
||||
role_code VARCHAR(64) NOT NULL,
|
||||
password_hash VARCHAR(256) NOT NULL,
|
||||
password_salt VARCHAR(128) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
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_auth_user_account_username (username),
|
||||
KEY idx_tms_auth_user_account_role_code (role_code)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tms_auth_session (
|
||||
id BIGINT PRIMARY KEY,
|
||||
session_token VARCHAR(128) NOT NULL,
|
||||
role_code VARCHAR(64) NOT NULL,
|
||||
authenticated_users_json JSON NULL,
|
||||
auth_method VARCHAR(32) NOT NULL,
|
||||
auth_level VARCHAR(32) NOT NULL,
|
||||
issued_at DATETIME(3) NOT NULL,
|
||||
@@ -378,7 +395,7 @@ VALUES
|
||||
11001,
|
||||
'SUPER_ADMIN',
|
||||
'超级管理员',
|
||||
3,
|
||||
2,
|
||||
'Viuew8WE+qziUZwGGU0x25cUpzsTF+QvQFU0uhb+yVA=',
|
||||
'init-super-admin-salt-20260325',
|
||||
'UNENABLED',
|
||||
@@ -394,7 +411,7 @@ VALUES
|
||||
11002,
|
||||
'KEY_ADMIN',
|
||||
'密钥管理员',
|
||||
2,
|
||||
1,
|
||||
'/xqmDy3A/q9X5p7XWznIPSBabQ6bxTLAPgtHQ6Be33c=',
|
||||
'init-key-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
@@ -439,6 +456,98 @@ VALUES
|
||||
CURRENT_TIMESTAMP(3)
|
||||
);
|
||||
|
||||
INSERT IGNORE INTO tms_auth_user_account (
|
||||
id,
|
||||
username,
|
||||
display_name,
|
||||
role_code,
|
||||
password_hash,
|
||||
password_salt,
|
||||
status,
|
||||
failed_count,
|
||||
locked_until,
|
||||
last_login_at,
|
||||
last_active_at,
|
||||
create_time,
|
||||
update_time
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
12001,
|
||||
'super-admin-01',
|
||||
'超级管理员账号一',
|
||||
'SUPER_ADMIN',
|
||||
'Viuew8WE+qziUZwGGU0x25cUpzsTF+QvQFU0uhb+yVA=',
|
||||
'init-super-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CURRENT_TIMESTAMP(3),
|
||||
CURRENT_TIMESTAMP(3)
|
||||
),
|
||||
(
|
||||
12002,
|
||||
'super-admin-02',
|
||||
'超级管理员账号二',
|
||||
'SUPER_ADMIN',
|
||||
'Viuew8WE+qziUZwGGU0x25cUpzsTF+QvQFU0uhb+yVA=',
|
||||
'init-super-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CURRENT_TIMESTAMP(3),
|
||||
CURRENT_TIMESTAMP(3)
|
||||
),
|
||||
(
|
||||
12003,
|
||||
'key-admin-01',
|
||||
'密钥管理员账号',
|
||||
'KEY_ADMIN',
|
||||
'/xqmDy3A/q9X5p7XWznIPSBabQ6bxTLAPgtHQ6Be33c=',
|
||||
'init-key-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CURRENT_TIMESTAMP(3),
|
||||
CURRENT_TIMESTAMP(3)
|
||||
),
|
||||
(
|
||||
12004,
|
||||
'audit-admin-01',
|
||||
'审计管理员账号',
|
||||
'AUDIT_ADMIN',
|
||||
'j/J1LKyUOzVEJfbbHe2dwKBKNdabRk502olk/LWIwhg=',
|
||||
'init-audit-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CURRENT_TIMESTAMP(3),
|
||||
CURRENT_TIMESTAMP(3)
|
||||
),
|
||||
(
|
||||
12005,
|
||||
'ops-admin-01',
|
||||
'运维管理员账号',
|
||||
'OPS_ADMIN',
|
||||
'2e9F4aCgsDb+AuD1LrBEqEg8yjy3ODo27UHtx06vj/A=',
|
||||
'init-ops-admin-salt-20260325',
|
||||
'ACTIVE',
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CURRENT_TIMESTAMP(3),
|
||||
CURRENT_TIMESTAMP(3)
|
||||
);
|
||||
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- IP白名单表
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<id property="id" column="id"/>
|
||||
<result property="sessionToken" column="session_token"/>
|
||||
<result property="roleCode" column="role_code"/>
|
||||
<result property="authenticatedUsersJson" column="authenticated_users_json"/>
|
||||
<result property="authMethod" column="auth_method"/>
|
||||
<result property="authLevel" column="auth_level"/>
|
||||
<result property="issuedAt" column="issued_at"/>
|
||||
@@ -22,6 +23,7 @@
|
||||
SELECT id,
|
||||
session_token,
|
||||
role_code,
|
||||
authenticated_users_json,
|
||||
auth_method,
|
||||
auth_level,
|
||||
issued_at,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cisd.tms.modules.auth.mapper.AuthUserAccountMapper">
|
||||
|
||||
<resultMap id="AuthUserAccountResultMap" type="com.cisd.tms.modules.auth.entity.AuthUserAccountEntity">
|
||||
<id property="id" column="id"/>
|
||||
<result property="username" column="username"/>
|
||||
<result property="displayName" column="display_name"/>
|
||||
<result property="roleCode" column="role_code"/>
|
||||
<result property="passwordHash" column="password_hash"/>
|
||||
<result property="passwordSalt" column="password_salt"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="failedCount" column="failed_count"/>
|
||||
<result property="lockedUntil" column="locked_until"/>
|
||||
<result property="lastLoginAt" column="last_login_at"/>
|
||||
<result property="lastActiveAt" column="last_active_at"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByUsername" parameterType="string" resultMap="AuthUserAccountResultMap">
|
||||
SELECT id,
|
||||
username,
|
||||
display_name,
|
||||
role_code,
|
||||
password_hash,
|
||||
password_salt,
|
||||
status,
|
||||
failed_count,
|
||||
locked_until,
|
||||
last_login_at,
|
||||
last_active_at,
|
||||
create_time,
|
||||
update_time
|
||||
FROM tms_auth_user_account
|
||||
WHERE username = #{username}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="selectByRoleCode" parameterType="string" resultMap="AuthUserAccountResultMap">
|
||||
SELECT id,
|
||||
username,
|
||||
display_name,
|
||||
role_code,
|
||||
password_hash,
|
||||
password_salt,
|
||||
status,
|
||||
failed_count,
|
||||
locked_until,
|
||||
last_login_at,
|
||||
last_active_at,
|
||||
create_time,
|
||||
update_time
|
||||
FROM tms_auth_user_account
|
||||
WHERE role_code = #{roleCode}
|
||||
ORDER BY username ASC
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -7,9 +7,7 @@
|
||||
<resultMap id="RoleUkeyBindingResultMap" type="com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity">
|
||||
<id property="id" column="id"/>
|
||||
<result property="roleCode" column="role_code"/>
|
||||
<result property="slotNo" column="slot_no"/>
|
||||
<result property="uid" column="uid"/>
|
||||
<result property="rid" column="rid"/>
|
||||
<result property="ukeySerial" column="ukey_serial"/>
|
||||
<result property="ukeyPubkey" column="ukey_pubkey"/>
|
||||
<result property="issuerSign" column="issuer_sign"/>
|
||||
@@ -20,12 +18,10 @@
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectActiveByRoleCodeAndSlotNo" resultMap="RoleUkeyBindingResultMap">
|
||||
<select id="selectActiveByRoleCodeAndUid" resultMap="RoleUkeyBindingResultMap">
|
||||
SELECT id,
|
||||
role_code,
|
||||
slot_no,
|
||||
uid,
|
||||
rid,
|
||||
ukey_serial,
|
||||
ukey_pubkey,
|
||||
issuer_sign,
|
||||
@@ -36,7 +32,7 @@
|
||||
update_time
|
||||
FROM tms_role_ukey_binding
|
||||
WHERE role_code = #{roleCode}
|
||||
AND slot_no = #{slotNo}
|
||||
AND uid = #{uid}
|
||||
AND status = 'ACTIVE'
|
||||
LIMIT 1
|
||||
</select>
|
||||
@@ -44,9 +40,7 @@
|
||||
<select id="selectActiveByRoleCode" parameterType="string" resultMap="RoleUkeyBindingResultMap">
|
||||
SELECT id,
|
||||
role_code,
|
||||
slot_no,
|
||||
uid,
|
||||
rid,
|
||||
ukey_serial,
|
||||
ukey_pubkey,
|
||||
issuer_sign,
|
||||
@@ -58,6 +52,6 @@
|
||||
FROM tms_role_ukey_binding
|
||||
WHERE role_code = #{roleCode}
|
||||
AND status = 'ACTIVE'
|
||||
ORDER BY slot_no ASC
|
||||
ORDER BY uid ASC
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user