diff --git a/pom.xml b/pom.xml index 4b97e1a..d9f6468 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,13 @@ 1.10.0 + + cn.hutool + hutool-all + 5.8.26 + + + com.sunyard.cisd device-fingerprint-tool diff --git a/src/main/java/com/cisd/tms/modules/datamac/entity/DataMacEntity.java b/src/main/java/com/cisd/tms/modules/datamac/entity/DataMacEntity.java new file mode 100644 index 0000000..9611ab5 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/datamac/entity/DataMacEntity.java @@ -0,0 +1,12 @@ +package com.cisd.tms.modules.datamac.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; + +@Data +public class DataMacEntity { + // 标记此字段在插入和更新时都需要自动填充 + @TableField(fill = FieldFill.INSERT_UPDATE) + private String mac; +} \ No newline at end of file diff --git a/src/main/java/com/cisd/tms/modules/datamac/hanlder/DataMacMetaObjectHandler.java b/src/main/java/com/cisd/tms/modules/datamac/hanlder/DataMacMetaObjectHandler.java new file mode 100644 index 0000000..a0038d9 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/datamac/hanlder/DataMacMetaObjectHandler.java @@ -0,0 +1,45 @@ +package com.cisd.tms.modules.datamac.hanlder; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.cisd.tms.modules.datamac.helper.Sm3MacCalculator; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +@Component +public class DataMacMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + // 插入时,直接基于当前实体对象计算 MAC + Object entity = metaObject.getOriginalObject(); + String mac = Sm3MacCalculator.calculateForEntity(entity); + this.strictInsertFill(metaObject, "mac", String.class, mac); + } + + @Override + public void updateFill(MetaObject metaObject) { + + } + +// @Override +// public void updateFill(MetaObject metaObject) { +// // 更新时,需要先获取 ID,再查询完整数据 +// Object entity = metaObject.getOriginalObject(); +// Object id = this.getFieldValByName("id", metaObject); +// if (id == null) { +// // 若没有 ID,则降级使用当前对象中的字段(不完整) +// String mac = Sm3MacCalculator.calculateForEntity(entity); +// this.strictUpdateFill(metaObject, "mac", String.class, mac); +// return; +// } +// +// // 通过 AOP 或手动调用 Service,在此处获取完整实体 +// Object fullEntity = fetchFullEntityFromService(entity.getClass(), id); +// if (fullEntity != null) { +// // 将当前更新内容合并到完整实体 +// mergeChanges(fullEntity, entity); +// String mac = Sm3MacCalculator.calculateForEntity(fullEntity); +// this.strictUpdateFill(metaObject, "mac", String.class, mac); +// } +// } +} diff --git a/src/main/java/com/cisd/tms/modules/datamac/helper/Sm3MacCalculator.java b/src/main/java/com/cisd/tms/modules/datamac/helper/Sm3MacCalculator.java new file mode 100644 index 0000000..9787377 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/datamac/helper/Sm3MacCalculator.java @@ -0,0 +1,39 @@ +package com.cisd.tms.modules.datamac.helper; +import cn.hutool.crypto.SmUtil; +import cn.hutool.core.util.ArrayUtil; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; + + + +public class Sm3MacCalculator { + public static String calculateForEntity(Object entity) { + // 1. 获取所有字段并按字段名排序,保证不同实体计算的顺序一致 + Field[] fields = entity.getClass().getDeclaredFields(); + Arrays.sort(fields, Comparator.comparing(Field::getName)); + + // 2. 构建待摘要的数据 + StringBuilder dataBuilder = new StringBuilder(); + for (Field field : fields) { + // 排除 mac 字段自身 + if ("mac".equals(field.getName())) { + continue; + } + try { + field.setAccessible(true); + Object value = field.get(entity); + dataBuilder.append(field.getName()).append("=") + .append(value != null ? value.toString() : "null") + .append(";"); + } catch (IllegalAccessException e) { + // 适当的日志记录 + throw new RuntimeException("Failed to read field: " + field.getName(), e); + } + } + + // 3. 生成最终的 SM3 哈希值 + return SmUtil.sm3(dataBuilder.toString()); + } +} diff --git a/src/main/java/com/cisd/tms/modules/datamac/interceptor/MacValidationInterceptor.java b/src/main/java/com/cisd/tms/modules/datamac/interceptor/MacValidationInterceptor.java new file mode 100644 index 0000000..2fb25d9 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/datamac/interceptor/MacValidationInterceptor.java @@ -0,0 +1,42 @@ +package com.cisd.tms.modules.datamac.interceptor; + + +import com.cisd.tms.modules.datamac.entity.DataMacEntity; +import com.cisd.tms.modules.datamac.helper.Sm3MacCalculator; +import org.apache.ibatis.executor.resultset.ResultSetHandler; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Signature; +import org.springframework.stereotype.Component; + +import java.sql.Statement; +import java.util.List; + + +@Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})) +@Component +public class MacValidationInterceptor implements Interceptor { + + @Override + public Object intercept(Invocation invocation) throws Throwable { + Object result = invocation.proceed(); + if (result instanceof List) { + ((List) result).forEach(this::validateEntity); + } else { + validateEntity(result); + } + return result; + } + + private void validateEntity(Object obj) { + if (obj instanceof DataMacEntity) { + DataMacEntity entity = (DataMacEntity) obj; + String storedMac = entity.getMac(); + String calculatedMac = Sm3MacCalculator.calculateForEntity(entity); + if (!storedMac.equals(calculatedMac)) { + throw new RuntimeException("Data integrity validation failed. The data has been tampered with."); + } + } + } +} \ No newline at end of file