🐛 修复 IAM 同步 dept_id 超长与手机号明文解密失败

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-14 15:13:19 +08:00
parent 6f4812db75
commit dee392eb48
8 changed files with 72 additions and 5 deletions
@@ -40,6 +40,13 @@ import java.util.List;
*/
public interface UserDeptMapper extends BaseMapper<UserDept> {
/**
* 提高当前会话 group_concat 上限,需与 queryUserDeptIds 在同一事务/连接中调用
*
* @param maxLen 最大长度
*/
void setGroupConcatMaxLen(@Param("maxLen") int maxLen);
/**
* 根据用户id列表查询对应的部门id列表拼接的字符串
* @param userIds
@@ -2,6 +2,10 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.system.mapper.UserDeptMapper">
<update id="setGroupConcatMaxLen">
SET SESSION group_concat_max_len = #{maxLen}
</update>
<select id="queryUserDeptIds" resultType="org.springblade.system.pojo.vo.UserDeptIdsVO">
select
group_concat(distinct bd.id) deptIds,
@@ -350,7 +350,20 @@ public class OaUserListSyncHelper {
String defaultRoleId = getDefaultRoleId();
List<User> updateUserParams = list.stream()
.filter(userDeptIds -> !unchangedUserIds.contains(userDeptIds.getUserId()))
.filter(userDeptIds -> StringUtils.isNotBlank(userDeptIds.getDeptIds()) && userDeptIds.getDeptIds().length() <= MAX_DEPT_ID_LENGTH)
.filter(userDeptIds -> {
if (StringUtils.isBlank(userDeptIds.getDeptIds())) {
return false;
}
int deptIdLength = userDeptIds.getDeptIds().length();
int deptCodesLength = StringUtils.length(userDeptIds.getDeptCodes());
if (deptIdLength > MAX_DEPT_ID_LENGTH || deptCodesLength > MAX_DEPT_ID_LENGTH) {
ComposeLogUtil.getLastLog().warn(
"用户部门字段超长已跳过回写 userId={} deptIdLen={} deptCodesLen={} max={}",
userDeptIds.getUserId(), deptIdLength, deptCodesLength, MAX_DEPT_ID_LENGTH);
return false;
}
return true;
})
.map(userDeptIds -> {
User user = new User();
user.setId(userDeptIds.getUserId());
@@ -46,11 +46,18 @@ import java.util.List;
@Service
public class UserDeptServiceImpl extends ServiceImpl<UserDeptMapper, UserDept> implements IUserDeptService {
/**
* 与 blade_user.dept_id / dept_codes 扩容后的字段上限一致
*/
private static final int GROUP_CONCAT_MAX_LEN = 2000;
@Override
public List<UserDeptIdsVO> queryUserDeptIds(Collection<Long> userIds) {
if (CollectionUtil.isEmpty(userIds)) {
return Collections.emptyList();
}
// 需与后续查询在同一连接中生效(外层事务内调用)
baseMapper.setGroupConcatMaxLen(GROUP_CONCAT_MAX_LEN);
return baseMapper.queryUserDeptIds(userIds);
}
@@ -1206,9 +1206,36 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
if (user == null) {
return;
}
if (user.getPhone() != null && user.getPhone().length() > 20) {
user.setPhone(SM2Util.decrypt(user.getPhone(), properties.getPublicKey(), properties.getPrivateKey()));
String phone = user.getPhone();
// 密文 Hex 通常远长于普通手机号;含 / 等非 Hex 字符的明文(如双号)直接跳过
if (StringUtil.isBlank(phone) || phone.length() <= 20 || !isSm2HexCipher(phone)) {
return;
}
try {
user.setPhone(SM2Util.decrypt(phone, properties.getPublicKey(), properties.getPrivateKey()));
} catch (Exception exception) {
log.warn("手机号 SM2 解密失败,保留原值 length={}", phone.length(), exception);
}
}
/**
* 判断是否为 SM2 密文 Hex(仅 0-9a-f,且偶数长度)
*/
private boolean isSm2HexCipher(String value) {
int length = value.length();
if ((length & 1) != 0) {
return false;
}
for (int index = 0; index < length; index++) {
char character = value.charAt(index);
boolean isDigit = character >= '0' && character <= '9';
boolean isLowerHex = character >= 'a' && character <= 'f';
boolean isUpperHex = character >= 'A' && character <= 'F';
if (!isDigit && !isLowerHex && !isUpperHex) {
return false;
}
}
return true;
}
@Override
+1 -1
View File
@@ -1265,7 +1265,7 @@ CREATE TABLE `blade_user` (
`birthday` datetime NULL DEFAULT NULL COMMENT '生日',
`sex` int NULL DEFAULT NULL COMMENT '性别',
`role_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色id',
`dept_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门id',
`dept_id` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门id',
`post_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '岗位id',
`leader_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '主管id',
`is_leader` int NULL DEFAULT 0 COMMENT '是否主管',
@@ -0,0 +1,9 @@
-- 用户多部门聚合字段扩容,避免 OA/IAM 同步时 dept_id 写入超长导致 Data truncation
-- 部署前先执行本脚本,再发布后端
ALTER TABLE `blade_user`
MODIFY COLUMN `dept_id` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门id';
-- 若库中已有 dept_codes 列,请同步执行以下语句(无该列时可跳过)
ALTER TABLE `blade_user`
MODIFY COLUMN `dept_codes` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门编码';
+1 -1
View File
@@ -5426,7 +5426,7 @@ CREATE TABLE `blade_user` (
`birthday` datetime DEFAULT NULL COMMENT '生日',
`sex` int(11) DEFAULT NULL COMMENT '性别',
`role_id` varchar(1000) DEFAULT NULL COMMENT '角色id',
`dept_id` varchar(1000) DEFAULT NULL COMMENT '部门id',
`dept_id` varchar(2000) DEFAULT NULL COMMENT '部门id',
`post_id` varchar(1000) DEFAULT NULL COMMENT '岗位id',
`leader_id` varchar(1000) DEFAULT NULL COMMENT '主管id',
`is_leader` int(11) DEFAULT '0' COMMENT '是否主管',