Browse Source

fix(dict): clear client-supplied audit fields in saveGroup/saveItem — prevent strictFill bypass forgery

saveGroup/saveItem accepted entity params whose createTime/creatorId/updaterId
were not sanitized; MetaObjectFillHandler uses strictInsertFill/strictUpdateFill
which only fills null fields, so client-supplied audit values were retained.
Now: null out all audit fields on entry (framework refills), restore
createTime/creatorId from exist on edit.
master
luoweijian 1 month ago
parent
commit
f3fba4a229
  1. 9
      crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java
  2. 9
      crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java

9
crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java

@ -69,6 +69,12 @@ public class DictGroupServiceImpl extends BaseServiceImpl<DictGroupMapper, DictG
if (group == null) { if (group == null) {
throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请求参数缺失"); throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请求参数缺失");
} }
// 审计字段由框架 strictInsertFill/strictUpdateFill 自动填充(仅 null 时填充),
// 客户端传入的审计值不可信且会被保留,统一清空防止伪造
group.setCreateTime(null);
group.setUpdateTime(null);
group.setCreatorId(null);
group.setUpdaterId(null);
if (StrUtil.isBlank(group.getName())) { if (StrUtil.isBlank(group.getName())) {
throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "分组名称不能为空"); throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "分组名称不能为空");
} }
@ -100,6 +106,9 @@ public class DictGroupServiceImpl extends BaseServiceImpl<DictGroupMapper, DictG
group.setStatus(exist.getStatus()); group.setStatus(exist.getStatus());
group.setBuiltin(exist.getBuiltin()); group.setBuiltin(exist.getBuiltin());
group.setDeleteKey(exist.getDeleteKey()); group.setDeleteKey(exist.getDeleteKey());
// 保留原始创建审计;updateTime/updaterId 保持 null 由 strictUpdateFill 填充
group.setCreateTime(exist.getCreateTime());
group.setCreatorId(exist.getCreatorId());
this.updateById(group); this.updateById(group);
} }
} }

9
crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java

@ -79,6 +79,12 @@ public class DictItemServiceImpl extends BaseServiceImpl<DictItemMapper, DictIte
if (item == null) { if (item == null) {
throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请求参数缺失"); throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请求参数缺失");
} }
// 审计字段由框架 strictInsertFill/strictUpdateFill 自动填充(仅 null 时填充),
// 客户端传入的审计值不可信且会被保留,统一清空防止伪造
item.setCreateTime(null);
item.setUpdateTime(null);
item.setCreatorId(null);
item.setUpdaterId(null);
if (item.getGroupId() == null) { if (item.getGroupId() == null) {
if (item.getId() == null) { if (item.getId() == null) {
throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请选择所属分组"); throw new BusinessErrorException(DictConstants.CODE_DICT_INVALID, "请选择所属分组");
@ -145,6 +151,9 @@ public class DictItemServiceImpl extends BaseServiceImpl<DictItemMapper, DictIte
item.setBuiltin(exist.getBuiltin()); item.setBuiltin(exist.getBuiltin());
item.setStatus(exist.getStatus()); item.setStatus(exist.getStatus());
item.setDeleteKey(exist.getDeleteKey()); item.setDeleteKey(exist.getDeleteKey());
// 保留原始创建审计;updateTime/updaterId 保持 null 由 strictUpdateFill 填充
item.setCreateTime(exist.getCreateTime());
item.setCreatorId(exist.getCreatorId());
checkValueMutable(exist, item.getValue()); checkValueMutable(exist, item.getValue());
checkItemValueUnique(exist.getGroupId(), item.getValue(), exist.getId()); checkItemValueUnique(exist.getGroupId(), item.getValue(), exist.getId());
this.updateById(item); this.updateById(item);

Loading…
Cancel
Save