Browse Source

优化用户同步需求

dev-V1.0.9
vincent 2 weeks ago
parent
commit
8d26e6d149
  1. 205
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bean/GdsztkY2010Dhr.java
  2. 148
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bean/GdsztkY2020Jb2.java
  3. 233
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/GdsztkY2010DhrVo.java
  4. 165
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/GdsztkY2020Jb2Vo.java
  5. 23
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/GdsztkY2010DhrMapper.java
  6. 23
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/GdsztkY2020Jb2Mapper.java
  7. 53
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/quartz/job/SynUserInfoJob.java
  8. 15
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IGdsztkY2020Jb2Service.java
  9. 40
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/GdsztkY2020Jb2ServiceSserviceImpl.java
  10. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/SrzUserServiceImpl.java
  11. 48
      zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/GdsztkY2010DhrMapper.xml
  12. 38
      zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/GdsztkY2020Jb2Mapper.xml
  13. 18
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/SysUser.java
  14. 17
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java
  15. 21
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java
  16. 74
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/CryptoSensitiveHsmServiceImpl.java

205
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bean/GdsztkY2010Dhr.java

@ -0,0 +1,205 @@
package com.zdxt.enforcementcode.domain.bean;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.util.Date;
/**
* 执法人员信息对象 s_gdsztk_y2010_dhr
*
* @author 庄锐波
* @date 2026-10-16
*/
@Data
@TableName("s_gdsztk_y2010_dhr")
public class GdsztkY2010Dhr {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标识ID
*/
@TableId(value = "ID")
private Long id;
/**
* 主键ID
*/
private String y201000;
/**
* 执法主体基本信息主键ID
*/
private String z202000;
/**
* 受委托组织基本信息ID
*/
private String z203000;
/**
* 姓名
*/
private String y201001;
/**
* 所属主体名称
*/
private String y201002;
/**
* 所属主体统一社会信用代码
*/
private String y201003;
/**
* 照片
*/
private String y201004;
/**
* 身份证号
*/
private String y201005;
/**
* 性别
*/
private String y201006;
/**
* 出生日期
*/
private Date y201007;
/**
* 政治面貌
*/
private String y201008;
/**
* 职级
*/
private String y201009;
/**
* 民族
*/
private String y201010;
/**
* 最高学历
*/
private String y201011;
/**
* 最高学历专业
*/
private String y201012;
/**
* 执法人员性质
*/
private String y201013;
/**
* 是否监督人员
*/
private Integer y201014;
/**
* 是否具有法律职业资格
*/
private Integer y201015;
/**
* 联系电话
*/
private String y201016;
/**
* 是否公开
*/
private Integer y201017;
/**
* 数据编目挂接单位名称
*/
private String y201018;
/**
* 数据编目挂接单位统一社会信用代码
*/
private String y201019;
/**
* 数据编目挂接单位行政区划
*/
private String y201020;
/**
* 创建时间
*/
private Date addTime;
/**
* 变更时间
*/
private Date cdTime;
/**
* 增量标识
*/
private String cdOperation;
/**
* 批次号
*/
private String cdBatch;
/**
* 数据所属单位区划
*/
private String optAreaCode;
/**
* 数据所属单位领域
*/
private String optFieldCode;
/**
* 数据所属单位主体ID
*/
private String optSubjectId;
/**
* 数据所属单位主体名称
*/
private String optSubjectName;
/**
* 数据所属单位部门ID
*/
private String optDeptId;
/**
* 数据所属单位部门名称
*/
private String optDeptName;
/**
* 运营方技术字段,非业务字段,请勿使用
*/
private Date dmpShareCdTimeIdatat;
/**
* 用数库自动配置的入库时间技术字段,非业务字段,请勿挂接
*/
private Date dataSharingCdTimeIdatat;
}

148
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bean/GdsztkY2020Jb2.java

@ -0,0 +1,148 @@
package com.zdxt.enforcementcode.domain.bean;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serial;
import java.util.Date;
/**
* 执法人员证件信息对象 s_gdsztk_y2020_jb2
*
* @author 庄锐波
* @date 2026-10-16
*/
@Data
@TableName("s_gdsztk_y2020_jb2")
public class GdsztkY2020Jb2 {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标识ID
*/
@TableId(value = "ID")
private Long id;
/**
* 主键ID
*/
private String y202000;
/**
* 执法人员基本信息主键ID
*/
private String y201000;
/**
* 证件编号
*/
private String y202001;
/**
* 持证人姓名
*/
private String y202002;
/**
* 证件类型
*/
private String y202003;
/**
* 发证日期
*/
private Date y202004;
/**
* 颁发机关
*/
private String y202005;
/**
* 证件状态
*/
private String y202006;
/**
* 执法区域
*/
private String y202007;
/**
* 数据编目挂接单位名称
*/
private String y202008;
/**
* 数据编目挂接单位统一社会信用代码
*/
private String y202009;
/**
* 数据编目挂接单位行政区划
*/
private String y202010;
/**
* 创建时间
*/
private Date addTime;
/**
* 变更时间
*/
private Date cdTime;
/**
* 增量标识
*/
private String cdOperation;
/**
* 批次号
*/
private String cdBatch;
/**
* 数据所属单位区划
*/
private String optAreaCode;
/**
* 数据所属单位领域
*/
private String optFieldCode;
/**
* 数据所属单位主体ID
*/
private String optSubjectId;
/**
* 数据所属单位主体名称
*/
private String optSubjectName;
/**
* 数据所属单位部门ID
*/
private String optDeptId;
/**
* 数据所属单位部门名称
*/
private String optDeptName;
/**
* 运营方技术字段,非业务字段,请勿使用
*/
private Date dmpShareCdTimeIdatat;
/**
* 用数库自动配置的入库时间技术字段,非业务字段,请勿挂接
*/
private Date dataSharingCdTimeIdatat;
}

233
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/GdsztkY2010DhrVo.java

@ -0,0 +1,233 @@
package com.zdxt.enforcementcode.domain.vo;
import java.util.Date;
import java.io.Serial;
import java.io.Serializable;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2010Dhr;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.sensitive.annotation.Sensitive;
import org.dromara.common.sensitive.core.SensitiveStrategy;
/**
* 执法人员信息视图对象 s_gdsztk_y2010_dhr
*
* @author 庄锐波
* @date 2026-10-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = GdsztkY2010Dhr.class)
public class GdsztkY2010DhrVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标识ID
*/
@ExcelProperty(value = "标识ID")
private Long id;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private String y201000;
/**
* 执法主体基本信息主键ID
*/
@ExcelProperty(value = "执法主体基本信息主键ID")
private String z202000;
/**
* 受委托组织基本信息ID
*/
@ExcelProperty(value = "受委托组织基本信息ID")
private String z203000;
/**
* 姓名
*/
@ExcelProperty(value = "姓名")
private String y201001;
/**
* 所属主体名称
*/
@ExcelProperty(value = "所属主体名称")
private String y201002;
/**
* 所属主体统一社会信用代码
*/
@ExcelProperty(value = "所属主体统一社会信用代码")
private String y201003;
/**
* 照片(不参与Excel导出)
*/
private String y201004;
/**
* 身份证号
*/
@ExcelProperty(value = "身份证号")
private String y201005;
/**
* 性别
*/
@ExcelProperty(value = "性别")
private String y201006;
/**
* 出生日期
*/
@ExcelProperty(value = "出生日期")
private Date y201007;
/**
* 政治面貌
*/
@ExcelProperty(value = "政治面貌")
private String y201008;
/**
* 职级
*/
@ExcelProperty(value = "职级")
private String y201009;
/**
* 民族
*/
@ExcelProperty(value = "民族")
private String y201010;
/**
* 最高学历
*/
@ExcelProperty(value = "最高学历")
private String y201011;
/**
* 最高学历专业
*/
@ExcelProperty(value = "最高学历专业")
private String y201012;
/**
* 执法人员性质
*/
@ExcelProperty(value = "执法人员性质")
private String y201013;
/**
* 是否监督人员
*/
@ExcelProperty(value = "是否监督人员")
private Integer y201014;
/**
* 是否具有法律职业资格
*/
@ExcelProperty(value = "是否具有法律职业资格")
private Integer y201015;
/**
* 联系电话
*/
@Sensitive(strategy = SensitiveStrategy.PHONE)
@ExcelProperty(value = "联系电话")
private String y201016;
/**
* 是否公开
*/
@ExcelProperty(value = "是否公开")
private Integer y201017;
/**
* 数据编目挂接单位名称
*/
@ExcelProperty(value = "数据编目挂接单位名称")
private String y201018;
/**
* 数据编目挂接单位统一社会信用代码
*/
@ExcelProperty(value = "数据编目挂接单位统一社会信用代码")
private String y201019;
/**
* 数据编目挂接单位行政区划
*/
@ExcelProperty(value = "数据编目挂接单位行政区划")
private String y201020;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date addTime;
/**
* 变更时间
*/
@ExcelProperty(value = "变更时间")
private Date cdTime;
/**
* 增量标识
*/
@ExcelProperty(value = "增量标识")
private String cdOperation;
/**
* 批次号
*/
@ExcelProperty(value = "批次号")
private String cdBatch;
/**
* 数据所属单位区划
*/
@ExcelProperty(value = "数据所属单位区划")
private String optAreaCode;
/**
* 数据所属单位领域
*/
@ExcelProperty(value = "数据所属单位领域")
private String optFieldCode;
/**
* 数据所属单位主体ID
*/
@ExcelProperty(value = "数据所属单位主体ID")
private String optSubjectId;
/**
* 数据所属单位主体名称
*/
@ExcelProperty(value = "数据所属单位主体名称")
private String optSubjectName;
/**
* 数据所属单位部门ID
*/
@ExcelProperty(value = "数据所属单位部门ID")
private String optDeptId;
/**
* 数据所属单位部门名称
*/
@ExcelProperty(value = "数据所属单位部门名称")
private String optDeptName;
}

165
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/GdsztkY2020Jb2Vo.java

@ -0,0 +1,165 @@
package com.zdxt.enforcementcode.domain.vo;
import java.util.Date;
import java.io.Serial;
import java.io.Serializable;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
/**
* 执法人员证件信息视图对象 s_gdsztk_y2020_jb2
*
* @author 庄锐波
* @date 2026-10-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = GdsztkY2020Jb2.class)
public class GdsztkY2020Jb2Vo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标识ID
*/
@ExcelProperty(value = "标识ID")
private Long id;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private String y202000;
/**
* 执法人员基本信息主键ID
*/
@ExcelProperty(value = "执法人员基本信息主键ID")
private String y201000;
/**
* 证件编号
*/
@ExcelProperty(value = "证件编号")
private String y202001;
/**
* 持证人姓名
*/
@ExcelProperty(value = "持证人姓名")
private String y202002;
/**
* 证件类型
*/
@ExcelProperty(value = "证件类型")
private String y202003;
/**
* 发证日期
*/
@ExcelProperty(value = "发证日期")
private Date y202004;
/**
* 颁发机关
*/
@ExcelProperty(value = "颁发机关")
private String y202005;
/**
* 证件状态
*/
@ExcelProperty(value = "证件状态")
private String y202006;
/**
* 执法区域
*/
@ExcelProperty(value = "执法区域")
private String y202007;
/**
* 数据编目挂接单位名称
*/
@ExcelProperty(value = "数据编目挂接单位名称")
private String y202008;
/**
* 数据编目挂接单位统一社会信用代码
*/
@ExcelProperty(value = "数据编目挂接单位统一社会信用代码")
private String y202009;
/**
* 数据编目挂接单位行政区划
*/
@ExcelProperty(value = "数据编目挂接单位行政区划")
private String y202010;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date addTime;
/**
* 变更时间
*/
@ExcelProperty(value = "变更时间")
private Date cdTime;
/**
* 增量标识
*/
@ExcelProperty(value = "增量标识")
private String cdOperation;
/**
* 批次号
*/
@ExcelProperty(value = "批次号")
private String cdBatch;
/**
* 数据所属单位区划
*/
@ExcelProperty(value = "数据所属单位区划")
private String optAreaCode;
/**
* 数据所属单位领域
*/
@ExcelProperty(value = "数据所属单位领域")
private String optFieldCode;
/**
* 数据所属单位主体ID
*/
@ExcelProperty(value = "数据所属单位主体ID")
private String optSubjectId;
/**
* 数据所属单位主体名称
*/
@ExcelProperty(value = "数据所属单位主体名称")
private String optSubjectName;
/**
* 数据所属单位部门ID
*/
@ExcelProperty(value = "数据所属单位部门ID")
private String optDeptId;
/**
* 数据所属单位部门名称
*/
@ExcelProperty(value = "数据所属单位部门名称")
private String optDeptName;
}

23
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/GdsztkY2010DhrMapper.java

@ -0,0 +1,23 @@
package com.zdxt.enforcementcode.mapper;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2010Dhr;
import com.zdxt.enforcementcode.domain.vo.GdsztkY2010DhrVo;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 执法人员信息Mapper接口
*
* @author 庄锐波
* @date 2026-10-16
*/
public interface GdsztkY2010DhrMapper extends BaseMapperPlus<GdsztkY2010Dhr, GdsztkY2010DhrVo> {
/**
* 根据身份证号码查询最新的一条记录数据
*
* @param idCard 身份证号码
* @return 最新的一条执法人员信息
*/
GdsztkY2010Dhr queryLatestByIdCard(@Param("idCard") String idCard);
}

23
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/mapper/GdsztkY2020Jb2Mapper.java

@ -0,0 +1,23 @@
package com.zdxt.enforcementcode.mapper;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2;
import com.zdxt.enforcementcode.domain.vo.GdsztkY2020Jb2Vo;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 执法人员证件信息Mapper接口
*
* @author 庄锐波
* @date 2026-10-16
*/
public interface GdsztkY2020Jb2Mapper extends BaseMapperPlus<GdsztkY2020Jb2, GdsztkY2020Jb2Vo> {
/**
* 根据执法人员基本信息主键ID查询证件状态有效(Y202006=01)的最新一条记录
*
* @param y201000 执法人员基本信息主键ID
* @return 最新的一条执法人员证件信息
*/
GdsztkY2020Jb2 queryLatestByY201000(@Param("y201000") String y201000);
}

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

@ -3,8 +3,10 @@ package com.zdxt.enforcementcode.quartz.job;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.zdxt.enforcementcode.common.util.IdCardCryptoUtil;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2;
import com.zdxt.enforcementcode.domain.bo.SrzUserBo;
import com.zdxt.enforcementcode.domain.vo.SrzUserVo;
import com.zdxt.enforcementcode.service.IGdsztkY2020Jb2Service;
import com.zdxt.enforcementcode.service.ISrzUserService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
@ -38,6 +40,9 @@ public class SynUserInfoJob {
@Autowired
private ICryptoSensitiveHsmService cryptoSensitiveHsmService;
@Autowired
private IGdsztkY2020Jb2Service gdsztkY2020Jb2Service;
public void run() {
this.userInfo();
}
@ -50,8 +55,10 @@ public class SynUserInfoJob {
int rowNom_srz = 0;
try {
while (true) {
//todo: 待优化,暂定查询指定数据
SrzUserBo srzUserBo = new SrzUserBo();
srzUserBo.setNeedUpdate(0L);
srzUserBo.setUsername("liufangyan1");
List<SrzUserVo> srzUserList = iSrzUserService.queryList(srzUserBo);
if (srzUserList == null || srzUserList.isEmpty()) break;
@ -97,14 +104,24 @@ public class SynUserInfoJob {
// 原有规则:证件号 AES 加密存入 sys_user 表
String certificateNumber = "";
try {
certificateNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getCertificatenumber());
} catch (Exception e) {
log.error("====> AES加密证件号失败: {}", e.getMessage());
if (StringUtils.isNotEmpty(srzUser.getCertificatenumber())) {
try {
certificateNumber = IdCardCryptoUtil.symmetricEncryptIdCard(secretKey, srzUser.getCertificatenumber());
} catch (Exception e) {
log.error("====> AES加密证件号失败: {}", e.getMessage());
}
}
sysUserBo.setCertificateNumber(certificateNumber);
sysUserBo.setIsMappingPerson(srzUser.getIsmappingperson());
sysUserBo.setDelFlag("0");
sysUserBo.setCryptoRemarkTwo(mobileNumber);
sysUserBo.setCryptoRemarkThree(certificateNumber);
//根据身份证信息查询执法人员信息
GdsztkY2020Jb2 gdsztkY2020Jb2 = gdsztkY2020Jb2Service.queryLatestCertByIdCard(srzUser.getCertificatenumber());
if(gdsztkY2020Jb2 != null && StringUtils.isNotEmpty(gdsztkY2020Jb2.getY202001())){
sysUserBo.setLawCertificateNum(gdsztkY2020Jb2.getY202001());
}
// 查询用户是否已存在(忽略数据权限)
SysUserVo uniqueUser = DataPermissionHelper.ignore(() -> sysUserService.selectUserByLoginName(userName));
@ -117,7 +134,7 @@ public class SynUserInfoJob {
String initPassword = RandomUtil.randomNumbers(8);
String md5Password = DigestUtil.md5Hex(userName + initPassword + sysUserBo.getSalt());
sysUserBo.setPassword(md5Password);
sysUserBo.setCryptoRemarkOne(md5Password);
log.info("====> 新增数据: {}", userName);
int rowNum = DataPermissionHelper.ignore(() -> sysUserService.insertUser(sysUserBo));
insertNum += rowNum;
@ -127,9 +144,14 @@ public class SynUserInfoJob {
sysUserBo.setUserId(uniqueUser.getUserId());
sysUserBo.setPassword(null);
sysUserBo.setSalt(null);
if (StringUtils.isEmpty(sysUserBo.getLawCertificateNum())) {
sysUserBo.setLawCertificateNum(uniqueUser.getLawCertificateNum());
// 补备份:存量用户密码备份缺失时,将库中当前密码备份到 crypto_remark_one
if (StringUtils.isEmpty(uniqueUser.getCryptoRemarkOne())
&& StringUtils.isNotEmpty(uniqueUser.getPassword())) {
sysUserBo.setCryptoRemarkOne(uniqueUser.getPassword());
}
// if (StringUtils.isEmpty(sysUserBo.getLawCertificateNum())) {
// sysUserBo.setLawCertificateNum(uniqueUser.getLawCertificateNum());
// }
log.info("====> 更新数据: {}", userName);
int rowNum = DataPermissionHelper.ignore(() -> sysUserService.updateUserById(sysUserBo));
@ -137,6 +159,7 @@ public class SynUserInfoJob {
userId = uniqueUser.getUserId();
}
// 密评规则:HSM 加密敏感字段存入 crypto_sensitive_data 表
String bizId = String.valueOf(userId);
try {
@ -148,11 +171,19 @@ public class SynUserInfoJob {
updateBo.setUserId(userId);
if (isNewUser) {
passwordCipher = cryptoSensitiveHsmService.encryptAndSave("sys_user", bizId, "password", sysUserBo.getPassword());
updateBo.setPassword(passwordCipher);
if (StringUtils.isNotEmpty(passwordCipher)) {
updateBo.setPassword(passwordCipher);
}
}
if (StringUtils.isNotEmpty(phoneCipher)) {
updateBo.setPhonenumber(phoneCipher);
}
if (StringUtils.isNotEmpty(idCardCipher)) {
updateBo.setCertificateNumber(idCardCipher);
}
if (updateBo.getPassword() != null || updateBo.getPhonenumber() != null || updateBo.getCertificateNumber() != null) {
DataPermissionHelper.ignore(() -> sysUserService.updateUserById(updateBo));
}
updateBo.setPhonenumber(phoneCipher);
updateBo.setCertificateNumber(idCardCipher);
DataPermissionHelper.ignore(() -> sysUserService.updateUserById(updateBo));
// 数据完整性摘要:基于 sys_user 表中最终存储值
String pwdForHash;

15
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IGdsztkY2020Jb2Service.java

@ -0,0 +1,15 @@
package com.zdxt.enforcementcode.service;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2;
public interface IGdsztkY2020Jb2Service {
/**
* 根据身份证号码查询执法证件信息(证件状态有效 Y202006=01 的最新一条)
*
* @param idCard 身份证号码
* @return 最新的一条执法人员证件信息,无匹配记录时返回 null
*/
GdsztkY2020Jb2 queryLatestCertByIdCard(String idCard);
}

40
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/GdsztkY2020Jb2ServiceSserviceImpl.java

@ -0,0 +1,40 @@
package com.zdxt.enforcementcode.service.impl;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2010Dhr;
import com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2;
import com.zdxt.enforcementcode.mapper.GdsztkY2010DhrMapper;
import com.zdxt.enforcementcode.mapper.GdsztkY2020Jb2Mapper;
import com.zdxt.enforcementcode.service.IGdsztkY2020Jb2Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 省数据
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class GdsztkY2020Jb2ServiceSserviceImpl implements IGdsztkY2020Jb2Service {
private final GdsztkY2020Jb2Mapper gdsztkY2020Jb2Mapper;
private final GdsztkY2010DhrMapper gdsztkY2010DhrMapper;
/**
* 根据身份证号码查询执法证件信息(证件状态有效 Y202006=01 的最新一条)
*
* @param idCard 身份证号码
* @return 最新的一条执法人员证件信息,无匹配记录时返回 null
*/
@Override
public GdsztkY2020Jb2 queryLatestCertByIdCard(String idCard) {
// 1. 根据身份证号码查询执法人员基本信息最新一条记录
GdsztkY2010Dhr dhr = gdsztkY2010DhrMapper.queryLatestByIdCard(idCard);
if (dhr == null || dhr.getY201000() == null || dhr.getY201000().isEmpty()) {
log.warn("根据身份证号码未查询到执法人员信息, idCard={}", idCard);
return null;
}
// 2. 根据执法人员基本信息主键ID查询有效证件最新一条记录
return gdsztkY2020Jb2Mapper.queryLatestByY201000(dhr.getY201000());
}
}

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

@ -88,8 +88,6 @@ public class SrzUserServiceImpl implements ISrzUserService {
*/
@Override
public List<SrzUserVo> queryList(SrzUserBo bo) {
//TODO 测试用
bo.setUsername("liufangyan1");
LambdaQueryWrapper<SrzUser> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}

48
zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/GdsztkY2010DhrMapper.xml

@ -0,0 +1,48 @@
<?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.zdxt.enforcementcode.mapper.GdsztkY2010DhrMapper">
<select id="queryLatestByIdCard" resultType="com.zdxt.enforcementcode.domain.bean.GdsztkY2010Dhr">
SELECT ID,
Y201000,
Z202000,
Z203000,
Y201001,
Y201002,
Y201003,
Y201004,
Y201005,
Y201006,
Y201007,
Y201008,
Y201009,
Y201010,
Y201011,
Y201012,
Y201013,
Y201014,
Y201015,
Y201016,
Y201017,
Y201018,
Y201019,
Y201020,
ADD_TIME,
CD_TIME,
CD_OPERATION,
CD_BATCH,
OPT_AREA_CODE,
OPT_FIELD_CODE,
OPT_SUBJECT_ID,
OPT_SUBJECT_NAME,
OPT_DEPT_ID,
OPT_DEPT_NAME
FROM s_gdsztk_y2010_dhr
WHERE Y201005 = #{idCard}
ORDER BY CD_TIME DESC, ID DESC
LIMIT 1
</select>
</mapper>

38
zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/GdsztkY2020Jb2Mapper.xml

@ -0,0 +1,38 @@
<?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.zdxt.enforcementcode.mapper.GdsztkY2020Jb2Mapper">
<select id="queryLatestByY201000" resultType="com.zdxt.enforcementcode.domain.bean.GdsztkY2020Jb2">
SELECT ID,
Y202000,
Y201000,
Y202001,
Y202002,
Y202003,
Y202004,
Y202005,
Y202006,
Y202007,
Y202008,
Y202009,
Y202010,
ADD_TIME,
CD_TIME,
CD_OPERATION,
CD_BATCH,
OPT_AREA_CODE,
OPT_FIELD_CODE,
OPT_SUBJECT_ID,
OPT_SUBJECT_NAME,
OPT_DEPT_ID,
OPT_DEPT_NAME
FROM s_gdsztk_y2020_jb2
WHERE Y201000 = #{y201000}
AND Y202006 = '01'
ORDER BY CD_TIME DESC, ID DESC
LIMIT 1
</select>
</mapper>

18
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/SysUser.java

@ -59,7 +59,7 @@ public class SysUser extends TenantEntity {
private String email;
/**
* 手机号码
* 手号码
*/
@TableField("phonenumber")
private String phonenumber;
@ -265,7 +265,23 @@ public class SysUser extends TenantEntity {
@TableField("rylb")
private String rylb;
/**
* 备份字段1
*/
@TableField("crypto_remark_one")
private String cryptoRemarkOne;
/**
* 备份字段2
*/
@TableField("crypto_remark_two")
private String cryptoRemarkTwo;
/**
* 备份字段3
*/
@TableField("crypto_remark_three")
private String cryptoRemarkThree;
public SysUser(Long userId) {
this.userId = userId;

17
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java

@ -341,6 +341,21 @@ public class SysUserBo extends BaseEntity {
*/
private String salt;
/**
* 备份字段1
*/
private String cryptoRemarkOne;
/**
* 备份字段2
*/
private String cryptoRemarkTwo;
/**
* 备份字段3
*/
private String cryptoRemarkThree;
/**
* 获取盐加密
*
@ -367,4 +382,6 @@ public class SysUserBo extends BaseEntity {
String hex= RandomUtil.randomString(USER_SALT_CHARS, USER_SALT_LENGTH);
setSalt(hex);
}
}

21
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java

@ -65,7 +65,7 @@ public class SysUserVo implements Serializable {
private String email;
/**
* 手机号码
* 手号码
*/
@Sensitive(strategy = SensitiveStrategy.PHONE, perms = "system:user:edit")
private String phonenumber;
@ -90,6 +90,25 @@ public class SysUserVo implements Serializable {
/** 证件号码 */
@JsonIgnore
private String certificateNumber;
/**
* 密码备份字段(HSM 密文替换前的原值)
*/
@JsonIgnore
private String cryptoRemarkOne;
/**
* 手机号备份字段(HSM 密文替换前的原值)
*/
@JsonIgnore
private String cryptoRemarkTwo;
/**
* 证件号备份字段(HSM 密文替换前的原值)
*/
@JsonIgnore
private String cryptoRemarkThree;
/**
* 盐加密
*/

74
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/CryptoSensitiveHsmServiceImpl.java

@ -246,14 +246,20 @@ public class CryptoSensitiveHsmServiceImpl implements ICryptoSensitiveHsmService
total++;
String bizId = String.valueOf(user.getUserId());
// password:存储值(MD5)直接作为 HSM 加密输入,口径与 SynUserInfoJob 一致
int r = initOneField(bizId, "password", user.getPassword(), "^[0-9a-f]{32}$", false);
// 成功后:原始值备份到 crypto_remark_one,password 字段替换为 HSM 密文
int r = initOneField(user, "password", user.getPassword(), "^[0-9a-f]{32}$", false);
if (r == 1) success++; else if (r == -1) fail++; else skip++;
// phonenumber / certificateNumber:存量已是 AES 密文,先 AES 加密(已有)再 HSM 加密
r = initOneField(bizId, "phonenumber", user.getPhonenumber(), null, true);
// phonenumber / certificateNumber:存量已是 AES 密文,AES 密文直接作为 HSM 输入(先 AES 后 HSM)
// 成功后:原始值备份到 crypto_remark_two,phonenumber 字段替换为 HSM 密文
r = initOneField(user, "phonenumber", user.getPhonenumber(), null, true);
if (r == 1) success++; else if (r == -1) fail++; else skip++;
r = initOneField(bizId, "certificateNumber", user.getCertificateNumber(), null, true);
// 成功后:原始值备份到 crypto_remark_three,certificateNumber 字段替换为 HSM 密文
r = initOneField(user, "certificateNumber", user.getCertificateNumber(), null, true);
if (r == 1) success++; else if (r == -1) fail++; else skip++;
// 备份字段 + 密文替换更新回 sys_user(须在完整性摘要之前落库,保证摘要口径与库中值一致)
updateSensitiveFields(user);
try {
doSaveIntegrityHash(TABLE_SYS_USER, bizId,
"password,phonenumber,certificateNumber",
@ -403,18 +409,25 @@ public class CryptoSensitiveHsmServiceImpl implements ICryptoSensitiveHsmService
}
/**
* 初始化单个敏感字段(幂等)
* 初始化单个敏感字段(幂等),成功后原始值备份到 crypto_remark_*,原字段替换为 HSM 密文
*
* @param plainPattern 明文形态兜底正则(aesCipherInput=false 时使用)
* @param aesCipherInput true=存储值为 AES 密文,AES 密文直接作为 HSM 加密输入(先 AES 后 HSM)
* @return 1=成功、0=跳过、-1=失败
*/
private int initOneField(String bizId, String fieldCode, String storedValue,
private int initOneField(SysUser user, String fieldCode, String storedValue,
String plainPattern, boolean aesCipherInput) {
String bizId = String.valueOf(user.getUserId());
if (StrUtil.isBlank(storedValue)) {
return 0;
}
if (queryActiveRecord(TABLE_SYS_USER, bizId, fieldCode) != null) {
CryptoSensitiveData existing = queryActiveRecord(TABLE_SYS_USER, bizId, fieldCode);
if (existing != null) {
// 已有密文记录(历史初始化过):直接用已有密文做备份+替换,保证重跑可补齐
if (StrUtil.isNotBlank(existing.getCipherText())) {
applyCipher(user, fieldCode, storedValue, existing.getCipherText());
return 1;
}
return 0;
}
String hsmInput;
@ -433,7 +446,11 @@ public class CryptoSensitiveHsmServiceImpl implements ICryptoSensitiveHsmService
}
}
try {
encryptAndSave(TABLE_SYS_USER, bizId, fieldCode, hsmInput);
String cipherText = encryptAndSave(TABLE_SYS_USER, bizId, fieldCode, hsmInput);
if (StrUtil.isBlank(cipherText)) {
return -1;
}
applyCipher(user, fieldCode, storedValue, cipherText);
return 1;
} catch (Exception e) {
log.error("存量数据初始化失败, bizId={}, fieldCode={}", bizId, fieldCode, e);
@ -441,6 +458,47 @@ public class CryptoSensitiveHsmServiceImpl implements ICryptoSensitiveHsmService
}
}
/**
* 原始值备份到 crypto_remark_*,原字段替换为 HSM 密文(仅修改内存对象,统一由 updateSensitiveFields 落库)
* password→crypto_remark_one、phonenumber→crypto_remark_two、certificateNumber→crypto_remark_three
*/
private void applyCipher(SysUser user, String fieldCode, String originalValue, String cipherText) {
switch (fieldCode) {
case "password" -> {
user.setCryptoRemarkOne(originalValue);
user.setPassword(cipherText);
}
case "phonenumber" -> {
user.setCryptoRemarkTwo(originalValue);
user.setPhonenumber(cipherText);
}
case "certificateNumber" -> {
user.setCryptoRemarkThree(originalValue);
user.setCertificateNumber(cipherText);
}
}
}
/**
* 将备份字段与密文替换结果更新回 sys_user(使用 wrapper 仅更新涉及列,不触发 update_time 自动填充)
*/
private void updateSensitiveFields(SysUser user) {
if (StrUtil.isBlank(user.getCryptoRemarkOne())
&& StrUtil.isBlank(user.getCryptoRemarkTwo())
&& StrUtil.isBlank(user.getCryptoRemarkThree())) {
return;
}
LambdaUpdateWrapper<SysUser> uw = new LambdaUpdateWrapper<>();
uw.eq(SysUser::getUserId, user.getUserId())
.set(StrUtil.isNotBlank(user.getCryptoRemarkOne()), SysUser::getCryptoRemarkOne, user.getCryptoRemarkOne())
.set(StrUtil.isNotBlank(user.getPassword()), SysUser::getPassword, user.getPassword())
.set(StrUtil.isNotBlank(user.getCryptoRemarkTwo()), SysUser::getCryptoRemarkTwo, user.getCryptoRemarkTwo())
.set(StrUtil.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
.set(StrUtil.isNotBlank(user.getCryptoRemarkThree()), SysUser::getCryptoRemarkThree, user.getCryptoRemarkThree())
.set(StrUtil.isNotBlank(user.getCertificateNumber()), SysUser::getCertificateNumber, user.getCertificateNumber());
sysUserMapper.update(null, uw);
}
/**
* 判断存储值是否为 AES 密文形态(用 srnwg.secretKey 尝试解密,成功即可解密)
*/

Loading…
Cancel
Save