Browse Source

用户表重要数据安全性与存储完整性开发

dev-V1.0.9
vincent 1 month ago
parent
commit
dcfce16959
  1. 4
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java
  2. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/QRCodeUtil.java
  3. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfSystemController.java
  4. 133
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/SynUserInfoJob.java
  5. 22
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/CryptoSensitiveHsmService.java
  6. 6
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseComplaintServiceImpl.java
  7. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseLoginServiceImpl.java
  8. 51
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/CryptoSensitiveHsmServiceImpl.java
  9. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/SrzUserServiceImpl.java
  10. 31
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/impl/PasswordPartyServiceImpl.java
  11. 8
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysUserService.java
  12. 6
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

4
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java

@ -170,7 +170,7 @@ public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
* 保存前的数据校验 * 保存前的数据校验
*/ */
private void validEntityBeforeSave(EfcodeVirtualUnit entity){ private void validEntityBeforeSave(EfcodeVirtualUnit entity){
//TODO 做一些数据校验,如唯一约束
} }
/** /**
@ -183,7 +183,7 @@ public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
@Override @Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){ if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
} }
// 删除前查询记录,获取 srzOrganizationId 用于清除 sys_dept.zone // 删除前查询记录,获取 srzOrganizationId 用于清除 sys_dept.zone
List<EfcodeVirtualUnit> units = baseMapper.selectBatchIds(ids); List<EfcodeVirtualUnit> units = baseMapper.selectBatchIds(ids);

2
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/QRCodeUtil.java

@ -357,11 +357,9 @@ public class QRCodeUtil {
return base; return base;
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} catch (WriterException e1) { } catch (WriterException e1) {
// TODO Auto-generated catch block
e1.printStackTrace(); e1.printStackTrace();
} }
return null; return null;

2
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfSystemController.java

@ -43,7 +43,7 @@ import java.util.Map;
* @Author: kylin * @Author: kylin
* @Date: 2024/5/1 3:00 下午 * @Date: 2024/5/1 3:00 下午
* @Version: 1.0 * @Version: 1.0
* @Desc: TODO * @Desc:
*/ */
@Slf4j @Slf4j
@Controller @Controller

133
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/SynUserInfoJob.java

@ -3,33 +3,27 @@ package com.zdxt.enforcementcode.quartz.job;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.DigestUtil;
import com.zdxt.enforcementcode.common.util.IdCardCryptoUtil; import com.zdxt.enforcementcode.common.util.IdCardCryptoUtil;
import com.zdxt.enforcementcode.domain.bean.UserSearchDto;
import com.zdxt.enforcementcode.domain.bo.SrzUserBo; import com.zdxt.enforcementcode.domain.bo.SrzUserBo;
import com.zdxt.enforcementcode.domain.vo.SrzUserVo; import com.zdxt.enforcementcode.domain.vo.SrzUserVo;
import com.zdxt.enforcementcode.service.CryptoSensitiveHsmService; import com.zdxt.enforcementcode.service.CryptoSensitiveHsmService;
import com.zdxt.enforcementcode.service.ISrzUserService; import com.zdxt.enforcementcode.service.ISrzUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.system.domain.bo.SysUserBo; import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysUserService; import org.dromara.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 同步用户信息定时任务 * 同步用户信息定时任务
*/ */
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor
public class SynUserInfoJob { public class SynUserInfoJob {
@Value("${srnwg.secretKey}") @Value("${srnwg.secretKey}")
@ -38,23 +32,18 @@ public class SynUserInfoJob {
@Autowired @Autowired
private ISrzUserService iSrzUserService; private ISrzUserService iSrzUserService;
@Autowired
private ISysDictDataService sysDictDataService;
@Autowired @Autowired
private ISysUserService sysUserService; private ISysUserService sysUserService;
@Autowired @Autowired
private CryptoSensitiveHsmService cryptoSensitiveHsmService; private CryptoSensitiveHsmService cryptoSensitiveHsmService;
public static Map<String,String> params = new HashMap<>(); public void run() {
public void run(){
this.userInfo(); this.userInfo();
} }
/** 同步用户数据 */ /** 同步用户数据 */
public void userInfo(){ public void userInfo() {
log.info("====================> 市认证原始表 -> 业务表 同步开始"); log.info("====================> 市认证原始表 -> 业务表 同步开始");
int insertNum = 0; int insertNum = 0;
int updateNum = 0; int updateNum = 0;
@ -64,10 +53,15 @@ public class SynUserInfoJob {
SrzUserBo srzUserBo = new SrzUserBo(); SrzUserBo srzUserBo = new SrzUserBo();
srzUserBo.setNeedUpdate(0L); srzUserBo.setNeedUpdate(0L);
List<SrzUserVo> srzUserList = iSrzUserService.queryList(srzUserBo); List<SrzUserVo> srzUserList = iSrzUserService.queryList(srzUserBo);
if (srzUserList == null || srzUserList.isEmpty() || srzUserList.size() == 0) break; if (srzUserList == null || srzUserList.isEmpty()) break;
for(SrzUserVo srzUser : srzUserList){ for (SrzUserVo srzUser : srzUserList) {
log.info("====> 获取数据: {}", srzUser.getUsername()); log.info("====> 获取数据: {}", srzUser.getUsername());
String userName = srzUser.getUsername();
if (StringUtils.isEmpty(userName)) {
continue;
}
SysUserBo sysUserBo = new SysUserBo(); SysUserBo sysUserBo = new SysUserBo();
sysUserBo.setSex(srzUser.getGendercode()); sysUserBo.setSex(srzUser.getGendercode());
sysUserBo.setDeptId(srzUser.getOrganizationid()); sysUserBo.setDeptId(srzUser.getOrganizationid());
@ -78,7 +72,7 @@ public class SynUserInfoJob {
sysUserBo.setUserName(srzUser.getFullname()); sysUserBo.setUserName(srzUser.getFullname());
sysUserBo.setTaskId(srzUser.getTaskid()); sysUserBo.setTaskId(srzUser.getTaskid());
sysUserBo.setSystemId(srzUser.getSystemid()); sysUserBo.setSystemId(srzUser.getSystemid());
sysUserBo.setLoginName(srzUser.getUsername()); sysUserBo.setLoginName(userName);
sysUserBo.setEffectOn(srzUser.getEffecton()); sysUserBo.setEffectOn(srzUser.getEffecton());
sysUserBo.setIsDisabled(srzUser.getIsdisabled()); sysUserBo.setIsDisabled(srzUser.getIsdisabled());
sysUserBo.setIsDeleted(srzUser.getIsdeleted()); sysUserBo.setIsDeleted(srzUser.getIsdeleted());
@ -93,7 +87,6 @@ public class SynUserInfoJob {
mobileNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getMobilenumber()); mobileNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getMobilenumber());
} catch (Exception e) { } catch (Exception e) {
log.error("====> AES加密手机号失败: {}", e.getMessage()); log.error("====> AES加密手机号失败: {}", e.getMessage());
mobileNumber = "";
} }
sysUserBo.setMobileNumber(mobileNumber); sysUserBo.setMobileNumber(mobileNumber);
sysUserBo.setPhonenumber(mobileNumber); sysUserBo.setPhonenumber(mobileNumber);
@ -108,61 +101,85 @@ public class SynUserInfoJob {
certificateNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getCertificatenumber()); certificateNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getCertificatenumber());
} catch (Exception e) { } catch (Exception e) {
log.error("====> AES加密证件号失败: {}", e.getMessage()); log.error("====> AES加密证件号失败: {}", e.getMessage());
certificateNumber = "";
} }
sysUserBo.setCertificateNumber(certificateNumber); sysUserBo.setCertificateNumber(certificateNumber);
sysUserBo.setIsMappingPerson(srzUser.getIsmappingperson()); sysUserBo.setIsMappingPerson(srzUser.getIsmappingperson());
sysUserBo.randomSalt();
sysUserBo.setDelFlag("0"); sysUserBo.setDelFlag("0");
// 原有规则:MD5(loginName + password + salt) 存入 sys_user.password // 查询用户是否已存在(忽略数据权限)
String initPassword = RandomUtil.randomNumbers(8); SysUserVo uniqueUser = DataPermissionHelper.ignore(() -> sysUserService.selectUserByLoginName(userName));
String md5Password = DigestUtil.md5Hex(sysUserBo.getLoginName() + initPassword + sysUserBo.getSalt()); Long userId;
sysUserBo.setPassword(md5Password); boolean isNewUser = (uniqueUser == null || uniqueUser.getUserId() == null);
String userName = srzUser.getUsername(); if (isNewUser) {
if(StringUtils.isNotEmpty(userName)){ // 新用户:初始化密码 + salt
SysUserVo uniqueUser = sysUserService.selectUserByLoginName(userName); sysUserBo.randomSalt();
Long userId; String initPassword = RandomUtil.randomNumbers(8);
if (null != uniqueUser && uniqueUser.getUserId() != null) { String md5Password = DigestUtil.md5Hex(userName + initPassword + sysUserBo.getSalt());
sysUserBo.setUserId(uniqueUser.getUserId()); sysUserBo.setPassword(md5Password);
if (StringUtils.isEmpty(sysUserBo.getLawCertificateNum())) {
sysUserBo.setLawCertificateNum(uniqueUser.getLawCertificateNum()); log.info("====> 新增数据: {}", userName);
} int rowNum = DataPermissionHelper.ignore(() -> sysUserService.insertUser(sysUserBo));
log.info("====> 更新数据: {}", srzUser.getUsername()); insertNum += rowNum;
int rowNum = DataPermissionHelper.ignore(() -> sysUserService.updateUser(sysUserBo)); userId = sysUserBo.getUserId();
updateNum += rowNum; } else {
userId = uniqueUser.getUserId(); // 已有用户:不重置密码,仅更新基本信息
} else { sysUserBo.setUserId(uniqueUser.getUserId());
log.info("====> 新增数据: {}", srzUser.getUsername()); sysUserBo.setPassword(null);
int rowNum = DataPermissionHelper.ignore(() -> sysUserService.insertUser(sysUserBo)); sysUserBo.setSalt(null);
insertNum += rowNum; if (StringUtils.isEmpty(sysUserBo.getLawCertificateNum())) {
userId = sysUserBo.getUserId(); sysUserBo.setLawCertificateNum(uniqueUser.getLawCertificateNum());
} }
// 密评规则:HSM 加密敏感字段存入 crypto_sensitive_data 表 log.info("====> 更新数据: {}", userName);
String bizId = String.valueOf(userId); int rowNum = DataPermissionHelper.ignore(() -> sysUserService.updateUserById(sysUserBo));
try { updateNum += rowNum;
cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "phonenumber", mobileNumber); userId = uniqueUser.getUserId();
cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "mobileNumber", mobileNumber); }
cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "certificateNumber", certificateNumber);
cryptoSensitiveHsmService.hashAndSavePassword("sys_user", bizId, md5Password);
} catch (Exception e) {
log.error("====> HSM加密敏感字段失败, userId={}, error={}", bizId, e.getMessage());
}
srzUser.setNeedUpdate(1L); // 密评规则:HSM 加密敏感字段存入 crypto_sensitive_data 表
int srz_num = iSrzUserService.update(srzUser); String bizId = String.valueOf(userId);
rowNom_srz += srz_num; try {
String phoneCipher = cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "phonenumber", mobileNumber);
String idCardCipher = cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "certificateNumber", certificateNumber);
// 密码:仅新用户进行 HSM 加密,已有用户密码不动
String passwordCipher = null;
SysUserBo updateBo = new SysUserBo();
updateBo.setUserId(userId);
if (isNewUser) {
passwordCipher = cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "password", sysUserBo.getPassword());
updateBo.setPassword(passwordCipher);
}
updateBo.setPhonenumber(phoneCipher);
updateBo.setCertificateNumber(idCardCipher);
DataPermissionHelper.ignore(() -> sysUserService.updateUserById(updateBo));
// 数据完整性摘要:基于 sys_user 表中最终存储值
String pwdForHash;
if (isNewUser) {
pwdForHash = StringUtils.isNotEmpty(passwordCipher) ? passwordCipher
: (StringUtils.isNotEmpty(sysUserBo.getPassword()) ? sysUserBo.getPassword() : "");
} else {
pwdForHash = (uniqueUser != null && StringUtils.isNotEmpty(uniqueUser.getPassword())) ? uniqueUser.getPassword() : "";
}
String phoneForHash = StringUtils.isNotEmpty(phoneCipher) ? phoneCipher : mobileNumber;
String idCardForHash = StringUtils.isNotEmpty(idCardCipher) ? idCardCipher : certificateNumber;
cryptoSensitiveHsmService.saveIntegrityHash("sys_user", bizId,
"password,phonenumber,certificateNumber",
pwdForHash, phoneForHash, idCardForHash);
} catch (Exception e) {
log.error("====> HSM加密敏感字段失败, userId={}, error={}", bizId, e.getMessage());
} }
// 无论 HSM 是否成功都标记已处理,避免死循环;HSM 失败由下次全量同步补偿
srzUser.setNeedUpdate(1L);
int srz_num = iSrzUserService.update(srzUser);
rowNom_srz += srz_num;
} }
} }
log.info("新增用户数量 : {} / 更新用户数量 : {} / 更新原始表数 : {}", insertNum, updateNum, rowNom_srz); log.info("新增用户数量 : {} / 更新用户数量 : {} / 更新原始表数 : {}", insertNum, updateNum, rowNom_srz);
} catch (Exception e) { } catch (Exception e) {
log.error("同步用户信息异常", e); log.error("同步用户信息异常", e);
e.printStackTrace();
} }
} }
} }

22
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/CryptoSensitiveHsmService.java

@ -1,5 +1,7 @@
package com.zdxt.enforcementcode.service; package com.zdxt.enforcementcode.service;
import com.zdxt.enforcementcode.domain.vo.passwordparty.SymmetryEncryptVo;
/** /**
* 密评敏感字段 HSM 加密服务 * 密评敏感字段 HSM 加密服务
* <p> * <p>
@ -10,17 +12,14 @@ public interface CryptoSensitiveHsmService {
/** /**
* 加密并存储敏感字段(SM4-CBC 对称加密) * 加密并存储敏感字段(SM4-CBC 对称加密)
* <p>
* 调用 HSM /hsm/api/symmetryEncrypt 接口加密,
* 密文存入 crypto_sensitive_data,同时写入审计记录。
* 若该 (tableName, bizId, fieldCode) 已有有效密文,先置为历史版本再插入新密文。
* *
* @param tableName 业务表名,如 sys_user * @param tableName 业务表名,如 sys_user
* @param bizId 业务记录主键 * @param bizId 业务记录主键
* @param fieldCode 字段编码,如 phone / id_card * @param fieldCode 字段编码,如 phone / id_card
* @param plainText 明文值 * @param plainText 明文值
* @return HSM 加密后的密文(cipherText),加密失败或明文为空时返回 null
*/ */
void encryptAndSave(String tableName, String bizId, String fieldCode, String plainText); String encryptAndSave(String tableName, String bizId, String fieldCode, String plainText);
/** /**
* 哈希并存储密码(HMAC-SM3 单向哈希) * 哈希并存储密码(HMAC-SM3 单向哈希)
@ -54,4 +53,17 @@ public interface CryptoSensitiveHsmService {
* @return 明文值,不存在则返回 null * @return 明文值,不存在则返回 null
*/ */
String decryptField(String tableName, String bizId, String fieldCode); String decryptField(String tableName, String bizId, String fieldCode);
/**
* 计算并存储数据完整性摘要(HMAC-SM3)
* <p>
* 将多个业务字段明文拼接后,调用 HSM HMAC-SM3 计算摘要,
* 结果存入 crypto_integrity_data 表,用于后续完整性校验。
*
* @param tableName 业务表名,如 sys_user
* @param bizId 业务记录主键
* @param fieldList 参与摘要的字段列表,逗号分隔,如 password,phonenumber,certificateNumber
* @param plainValues 与 fieldList 顺序一致的明文值
*/
void saveIntegrityHash(String tableName, String bizId, String fieldList, String... plainValues);
} }

6
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseComplaintServiceImpl.java

@ -271,7 +271,7 @@ public class AppEnterpriseComplaintServiceImpl implements IAppEnterpriseComplain
* 保存前的数据校验 * 保存前的数据校验
*/ */
private void validEntityBeforeSave(EnterpriseComplaint entity){ private void validEntityBeforeSave(EnterpriseComplaint entity){
//TODO 做一些数据校验,如唯一约束
} }
/** /**
@ -284,7 +284,7 @@ public class AppEnterpriseComplaintServiceImpl implements IAppEnterpriseComplain
@Override @Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){ if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
@ -359,7 +359,7 @@ public class AppEnterpriseComplaintServiceImpl implements IAppEnterpriseComplain
mssqAddOrder.setProWoCode(appEnterpriseComplaintVo.getProWoCode()); mssqAddOrder.setProWoCode(appEnterpriseComplaintVo.getProWoCode());
String mssq =null; String mssq =null;
try { try {
//查询进度详细信息 TODO 异常捕捉之后,前端超时
mssq = mssqApiService.queryMssq(mssqAddOrder, "/api/API_YX/proProcess/queryAppInfo"); mssq = mssqApiService.queryMssq(mssqAddOrder, "/api/API_YX/proProcess/queryAppInfo");
log.info("查询工单信息结果返回:{}",mssq); log.info("查询工单信息结果返回:{}",mssq);
JSONObject jsonObject = JSONObject.parseObject(mssq); JSONObject jsonObject = JSONObject.parseObject(mssq);

2
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseLoginServiceImpl.java

@ -376,7 +376,7 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
log.info("企业信息更新成功: enterpriseNumber={}, enterpriseId={}", log.info("企业信息更新成功: enterpriseNumber={}, enterpriseId={}",
enterpriseNumber, existingEnterprise.getId()); enterpriseNumber, existingEnterprise.getId());
// // TODO: 2026/5/13 测试时候使用,生产环境需要关闭
// qrCodeGenerate(existingEnterprise); // qrCodeGenerate(existingEnterprise);
return existingEnterprise; return existingEnterprise;
} else { } else {

51
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/CryptoSensitiveHsmServiceImpl.java

@ -4,9 +4,11 @@ import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zdxt.enforcementcode.domain.bean.CryptoIntegrityData;
import com.zdxt.enforcementcode.domain.bean.CryptoOperationAudit; import com.zdxt.enforcementcode.domain.bean.CryptoOperationAudit;
import com.zdxt.enforcementcode.domain.bean.CryptoSensitiveData; import com.zdxt.enforcementcode.domain.bean.CryptoSensitiveData;
import com.zdxt.enforcementcode.domain.vo.passwordparty.SymmetryEncryptVo; import com.zdxt.enforcementcode.domain.vo.passwordparty.SymmetryEncryptVo;
import com.zdxt.enforcementcode.mapper.CryptoIntegrityDataMapper;
import com.zdxt.enforcementcode.mapper.CryptoOperationAuditMapper; import com.zdxt.enforcementcode.mapper.CryptoOperationAuditMapper;
import com.zdxt.enforcementcode.mapper.CryptoSensitiveDataMapper; import com.zdxt.enforcementcode.mapper.CryptoSensitiveDataMapper;
import com.zdxt.enforcementcode.service.CryptoSensitiveHsmService; import com.zdxt.enforcementcode.service.CryptoSensitiveHsmService;
@ -19,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Date;
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@ -28,15 +31,16 @@ public class CryptoSensitiveHsmServiceImpl implements CryptoSensitiveHsmService
private final IPasswordPartyService passwordPartyService; private final IPasswordPartyService passwordPartyService;
private final CryptoSensitiveDataMapper cryptoSensitiveDataMapper; private final CryptoSensitiveDataMapper cryptoSensitiveDataMapper;
private final CryptoOperationAuditMapper cryptoOperationAuditMapper; private final CryptoOperationAuditMapper cryptoOperationAuditMapper;
private final CryptoIntegrityDataMapper cryptoIntegrityDataMapper;
private static final String KEY_VERSION = "V1"; private static final String KEY_VERSION = "V1";
private static final String TABLE_SYS_USER = "sys_user"; private static final String TABLE_SYS_USER = "sys_user";
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void encryptAndSave(String tableName, String bizId, String fieldCode, String plainText) { public String encryptAndSave(String tableName, String bizId, String fieldCode, String plainText) {
if (StrUtil.isBlank(plainText)) { if (StrUtil.isBlank(plainText)) {
return; return null;
} }
String inputHex = HexUtil.encodeHexStr(plainText.getBytes(StandardCharsets.UTF_8)); String inputHex = HexUtil.encodeHexStr(plainText.getBytes(StandardCharsets.UTF_8));
SymmetryEncryptVo encryptResult = passwordPartyService.symmetryEncrypt(inputHex); SymmetryEncryptVo encryptResult = passwordPartyService.symmetryEncrypt(inputHex);
@ -65,6 +69,7 @@ public class CryptoSensitiveHsmServiceImpl implements CryptoSensitiveHsmService
cryptoSensitiveDataMapper.insert(record); cryptoSensitiveDataMapper.insert(record);
saveAuditRecord(tableName, bizId, fieldCode, record.getId(), 1, "HSM SM4-CBC 加密存储"); saveAuditRecord(tableName, bizId, fieldCode, record.getId(), 1, "HSM SM4-CBC 加密存储");
} }
return encryptResult.getOutData();
} }
@Override @Override
@ -73,8 +78,7 @@ public class CryptoSensitiveHsmServiceImpl implements CryptoSensitiveHsmService
if (StrUtil.isBlank(plainPassword)) { if (StrUtil.isBlank(plainPassword)) {
return null; return null;
} }
encryptAndSave(tableName, bizId, "password", plainPassword); return encryptAndSave(tableName, bizId, "password", plainPassword);
return null;
} }
@Override @Override
@ -105,6 +109,45 @@ public class CryptoSensitiveHsmServiceImpl implements CryptoSensitiveHsmService
return new String(plainBytes, StandardCharsets.UTF_8); return new String(plainBytes, StandardCharsets.UTF_8);
} }
@Override
@Transactional(rollbackFor = Exception.class)
public void saveIntegrityHash(String tableName, String bizId, String fieldList, String... plainValues) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < plainValues.length; i++) {
if (i > 0) sb.append(",");
sb.append(plainValues[i] != null ? plainValues[i] : "");
}
String concatPlain = sb.toString();
String inputHex = HexUtil.encodeHexStr(concatPlain.getBytes(StandardCharsets.UTF_8));
String hmacHash = passwordPartyService.hmacWithIndex(inputHex);
LambdaQueryWrapper<CryptoIntegrityData> lqw = new LambdaQueryWrapper<>();
lqw.eq(CryptoIntegrityData::getTableName, tableName)
.eq(CryptoIntegrityData::getBizId, bizId)
.eq(CryptoIntegrityData::getIsDeleted, 0);
CryptoIntegrityData existing = cryptoIntegrityDataMapper.selectOne(lqw);
if (existing != null) {
existing.setFieldList(fieldList);
existing.setSm3Hash(hmacHash);
existing.setHashAlg("SM3");
existing.setGenerateTime(new Date());
existing.setVerifyResult(0);
cryptoIntegrityDataMapper.updateById(existing);
} else {
CryptoIntegrityData record = new CryptoIntegrityData();
record.setTableName(tableName);
record.setBizId(bizId);
record.setFieldList(fieldList);
record.setSm3Hash(hmacHash);
record.setHashAlg("SM3");
record.setGenerateTime(new Date());
record.setVerifyResult(0);
record.setIsDeleted(0);
cryptoIntegrityDataMapper.insert(record);
}
}
private CryptoSensitiveData queryActiveRecord(String tableName, String bizId, String fieldCode) { private CryptoSensitiveData queryActiveRecord(String tableName, String bizId, String fieldCode) {
LambdaQueryWrapper<CryptoSensitiveData> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CryptoSensitiveData> lqw = new LambdaQueryWrapper<>();
lqw.eq(CryptoSensitiveData::getTableName, tableName) lqw.eq(CryptoSensitiveData::getTableName, tableName)

2
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/SrzUserServiceImpl.java

@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.glassfish.jaxb.core.v2.TODO;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.zdxt.enforcementcode.domain.bo.SrzUserBo; import com.zdxt.enforcementcode.domain.bo.SrzUserBo;
@ -87,6 +88,7 @@ public class SrzUserServiceImpl implements ISrzUserService {
*/ */
@Override @Override
public List<SrzUserVo> queryList(SrzUserBo bo) { public List<SrzUserVo> queryList(SrzUserBo bo) {
//TODO 测试用
bo.setUsername("liufangyan1"); bo.setUsername("liufangyan1");
LambdaQueryWrapper<SrzUser> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<SrzUser> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw); return baseMapper.selectVoList(lqw);

31
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/impl/PasswordPartyServiceImpl.java

@ -51,16 +51,16 @@ public class PasswordPartyServiceImpl implements IPasswordPartyService {
*/ */
@Override @Override
public SymmetryEncryptVo symmetryEncrypt(String inputData) { public SymmetryEncryptVo symmetryEncrypt(String inputData) {
//TODO 生成随机数,目前使用SecureRandom,后续需要替换为HSM生成随机数 // TODO 生成随机数,目前使用SecureRandom,后续需要替换为HSM生成随机数
// String iv = generateRandom(16); String iv = generateRandom(16);
SecureRandom secureRandom = new SecureRandom(); // SecureRandom secureRandom = new SecureRandom();
byte[] ivBytes = new byte[16]; // byte[] ivBytes = new byte[16];
secureRandom.nextBytes(ivBytes); // secureRandom.nextBytes(ivBytes);
StringBuilder sb = new StringBuilder(); // StringBuilder sb = new StringBuilder();
for (byte b : ivBytes) { // for (byte b : ivBytes) {
sb.append(String.format("%02x", b)); // sb.append(String.format("%02x", b));
} // }
String iv = sb.toString(); // String iv = sb.toString();
JSONObject params = buildSymmetryParams(iv, inputData); JSONObject params = buildSymmetryParams(iv, inputData);
JSONObject data = callHsmApi("/hsm/api/symmetryEncrypt", params, "对称加密"); JSONObject data = callHsmApi("/hsm/api/symmetryEncrypt", params, "对称加密");
@ -203,13 +203,12 @@ public class PasswordPartyServiceImpl implements IPasswordPartyService {
* @return 响应中的data节点 * @return 响应中的data节点
*/ */
private JSONObject callHsmApi(String apiPath, JSONObject params, String apiName) { private JSONObject callHsmApi(String apiPath, JSONObject params, String apiName) {
//TODO 测试数据 JSONObject jsonObject = doPost(apiPath, params, apiName);
// JSONObject jsonObject = doPost(apiPath, params, apiName); JSONObject data = jsonObject.getJSONObject("data");
// JSONObject data = jsonObject.getJSONObject("data"); //TODO 测试数据
// String jsonStr = "{\"outData\":\"8216fc247b987ca99e9b5f77b375ed1a\",\"ivData\":\"123\"}";
String jsonStr = "{\"outData\":\"8216fc247b987ca99e9b5f77b375ed1a\",\"ivData\":\"123\"}"; // JSONObject data = JSONObject.parseObject(jsonStr);
JSONObject data = JSONObject.parseObject(jsonStr);
if (data == null) { if (data == null) {
throw new BaseException("HSM" + apiName + "响应data为空"); throw new BaseException("HSM" + apiName + "响应data为空");

8
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysUserService.java

@ -173,6 +173,14 @@ public interface ISysUserService {
*/ */
int updateUser(SysUserBo user); int updateUser(SysUserBo user);
/**
* 仅更新用户指定字段(不处理角色/岗位关联)
*
* @param user 用户信息(仅更新非空字段)
* @return 结果
*/
int updateUserById(SysUserBo user);
/** /**
* 用户授权角色 * 用户授权角色
* *

6
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

@ -379,6 +379,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
return flag; return flag;
} }
@Override
public int updateUserById(SysUserBo user) {
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
return baseMapper.updateById(sysUser);
}
/** /**
* 用户授权角色 * 用户授权角色
* *

Loading…
Cancel
Save