审计组件

news/2025/10/31 17:06:40/文章来源:https://www.cnblogs.com/aibi1/p/19180562

目录
  • 背景和价值
        • 2. 为什么不建议切DAO层?
  • 记录变更日志的方案 - 半自动化方案
      • 一、核心设计:敏感信息变更流水表(快照表)
      • 二、实现思路:业务变更时自动记录快照
        • 1. 标记敏感实体/字段(明确需要记录的信息)
        • 2. 快照记录时机:Service层事务内触发
        • 3. 通用快照处理服务(SensitiveLogService)
      • 三、优势:为何适合敏感信息合规场景?
      • 四、优化与注意事项
      • 总结
  • 参考资料

背景和价值

为什么切Service层?

  • 业务上下文完整:Service层的方法(如updateOrderupdateUser)是业务操作的入口,参数通常是前端传递的DTO或领域对象,包含完整的修改信息,便于直接与数据库原始DO对比。
  • 切入点明确:Service层方法命名规范(如updateXXXmodifyXXX),容易通过AOP表达式拦截(如execution(* com.xxx.service.*.update*(..))),且能精准匹配“修改操作”。
  • 支持业务过滤:可在AOP中结合业务逻辑判断是否需要记录变更(如某些状态的订单不允许修改,可直接跳过对比)。

2. 为什么不建议切DAO层?

  • 缺乏业务上下文:DAO层方法(如saveupdate)通常接收的是DO,此时原始DO和修改后DO的差异可能已被Service层处理(如自动填充更新时间),导致对比结果包含非业务修改(如系统字段)。
  • 切入点模糊:DAO层的update方法可能被多个业务场景调用(如创建、修改、批量操作),难以区分“是否需要跟踪变更”。
  • 性能问题:DAO层方法可能被高频调用(如批量更新),在此切入会增加不必要的查询和对比开销。

记录变更日志的方案 - 半自动化方案

安全隐私合规要求,比如欧洲GDPR等需要记录个人隐私信息, 敏感业务信息(电商的价格)等。

你的思路非常贴合安全合规的核心诉求——敏感信息的变更必须留下可追溯的审计轨迹,而“流水表+快照”模式正是行业内处理这类需求的成熟方案。相比AOP实时对比字段,这种方式更侧重“结果留存”,尤其适合对合规性要求高的场景(如个人隐私、金融价格、电商订单核心信息等)。

一、核心设计:敏感信息变更流水表(快照表)

首先需要设计一张通用的流水表,用于存储敏感信息的变更快照。表结构需包含“业务标识”“变更前后快照”“操作上下文”三大核心要素,示例如下:

字段名 类型 说明
id bigint 流水唯一ID(主键)
business_type varchar(50) 业务类型(如"USER"用户、"ORDER"订单、"PRODUCT"商品)
business_id varchar(64) 业务对象ID(如用户ID、订单号、商品ID,关联具体业务数据)
old_snapshot text/json 变更前快照(完整记录敏感字段的原始值,建议JSON格式存储)
new_snapshot text/json 变更后快照(完整记录敏感字段的新值,JSON格式)
change_fields varchar(2000) 本次变更的敏感字段列表(如"phone,address",便于快速检索)
operator_id varchar(64) 操作人ID(记录是谁修改的,关联用户表)
operator_ip varchar(50) 操作IP地址(合规审计要求)
operation_time datetime 操作时间
operation_type varchar(20) 操作类型("INSERT"新增、"UPDATE"修改、"DELETE"删除)
remark varchar(500) 备注(如修改原因,可选)

二、实现思路:业务变更时自动记录快照

核心是在敏感信息发生变更的业务节点(如更新用户手机号、修改商品价格),自动触发快照记录,确保“数据变更”与“流水记录”在同一事务中,保证一致性。

1. 标记敏感实体/字段(明确需要记录的信息)

通过注解标记哪些实体或字段属于敏感信息,避免非敏感信息冗余存储。示例:

// 标记敏感实体(类级别)
@SensitiveEntity(businessType = "USER") // 业务类型:用户
public class User {private Long id; // 业务ID(用户ID)// 标记敏感字段(字段级别)@SensitiveField(description = "手机号")private String phone;@SensitiveField(description = "家庭地址")private String address;private String nickname; // 非敏感字段,无需记录快照// getter/setter
}// 商品价格(敏感业务信息)
@SensitiveEntity(businessType = "PRODUCT")
public class Product {private Long id;@SensitiveField(description = "售价") // 价格属于敏感业务信息private BigDecimal price;private String name; // 非敏感字段
}

2. 快照记录时机:Service层事务内触发

在Service层执行敏感信息修改逻辑时,先查询原始数据(变更前快照),执行修改后,再记录新快照,并将两者存入流水表。核心是与业务操作在同一事务中,确保数据修改成功则流水必存,修改失败则流水不存。

示例代码(以修改用户手机号为例):

@Service
@Transactional
public class UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate SensitiveLogService sensitiveLogService; // 流水记录服务// 修改用户手机号(敏感操作)public void updateUserPhone(Long userId, String newPhone, OperatorContext context) {// 1. 查询原始数据(变更前快照)User originalUser = userMapper.selectById(userId);if (originalUser == null) {throw new RuntimeException("用户不存在");}// 2. 执行修改(业务逻辑)User updatedUser = new User();updatedUser.setId(userId);updatedUser.setPhone(newPhone);userMapper.updateById(updatedUser);// 3. 记录快照流水(自动提取敏感字段)sensitiveLogService.recordLog(originalUser,    // 旧快照updatedUser,     // 新快照context          // 操作上下文(操作人、IP等));}
}

3. 通用快照处理服务(SensitiveLogService)

封装快照生成、字段对比、流水存储的通用逻辑,避免业务代码重复:

@Service
public class SensitiveLogService {@Autowiredprivate SensitiveLogMapper sensitiveLogMapper;@Autowiredprivate ObjectMapper objectMapper; // Jackson,用于JSON序列化/*** 记录敏感信息变更流水* @param original 变更前对象(需标记@SensitiveEntity)* @param updated 变更后对象* @param context 操作上下文(操作人、IP等)*/public void recordLog(Object original, Object updated, OperatorContext context) {// 1. 校验是否为敏感实体SensitiveEntity sensitiveEntity = original.getClass().getAnnotation(SensitiveEntity.class);if (sensitiveEntity == null) {throw new RuntimeException("实体未标记@SensitiveEntity,不支持记录流水");}// 2. 提取业务标识(businessType + businessId)String businessType = sensitiveEntity.businessType();Long businessId = getBusinessId(original); // 反射获取ID字段(如User.id)// 3. 生成快照(仅包含@SensitiveField标记的字段)Map<String, Object> oldSnapshot = extractSensitiveFields(original);Map<String, Object> newSnapshot = extractSensitiveFields(updated);// 4. 对比变更的敏感字段Set<String> changeFields = findChangedFields(oldSnapshot, newSnapshot);// 5. 构建流水记录SensitiveLog log = new SensitiveLog();log.setBusinessType(businessType);log.setBusinessId(businessId.toString());log.setOldSnapshot(objectMapper.writeValueAsString(oldSnapshot)); // 旧快照JSONlog.setNewSnapshot(objectMapper.writeValueAsString(newSnapshot)); // 新快照JSONlog.setChangeFields(String.join(",", changeFields));log.setOperatorId(context.getOperatorId());log.setOperatorIp(context.getIp());log.setOperationTime(new Date());log.setOperationType("UPDATE"); // 此处为修改,新增/删除需单独处理// 6. 保存流水(与业务操作在同一事务)sensitiveLogMapper.insert(log);}// 反射提取对象中@SensitiveField标记的字段private Map<String, Object> extractSensitiveFields(Object obj) {Map<String, Object> fields = new HashMap<>();Field[] allFields = obj.getClass().getDeclaredFields();for (Field field : allFields) {if (field.isAnnotationPresent(SensitiveField.class)) {field.setAccessible(true);try {fields.put(field.getName(), field.get(obj));} catch (IllegalAccessException e) {// 忽略无法访问的字段}}}return fields;}// 对比新旧快照,找出变更的字段private Set<String> findChangedFields(Map<String, Object> oldMap, Map<String, Object> newMap) {Set<String> changed = new HashSet<>();for (String field : oldMap.keySet()) {Object oldVal = oldMap.get(field);Object newVal = newMap.getOrDefault(field, null);if (!Objects.equals(oldVal, newVal)) {changed.add(field);}}return changed;}// 反射获取业务ID(假设ID字段名为"id",或通过@Id注解标记)private Long getBusinessId(Object obj) {try {Field idField = obj.getClass().getDeclaredField("id");idField.setAccessible(true);return (Long) idField.get(obj);} catch (Exception e) {throw new RuntimeException("未找到业务ID字段(id)", e);}}
}

三、优势:为何适合敏感信息合规场景?

  1. 可追溯性强:流水表完整保存变更前后的快照,审计时可直接查询历史记录,明确“谁在何时修改了什么”,满足GDPR、等保2.0等合规要求。
  2. 与业务解耦:通过通用服务(SensitiveLogService)和注解,业务代码只需调用记录方法,无需关注快照生成和存储细节,侵入性低。
  3. 灵活性高:支持任意敏感实体(用户、订单、商品等),通过business_type区分,一张流水表可满足多业务场景。
  4. 安全性:快照仅包含@SensitiveField标记的字段,避免非敏感信息泄露(如用户昵称无需记录),同时可对流水表单独设置权限(如仅审计人员可查)。

四、优化与注意事项

  1. 性能优化

    • 快照字段(old_snapshotnew_snapshot)建议用JSON类型(如MySQL的json),便于查询特定字段的历史(如where business_type='USER' and business_id='123' and JSON_EXTRACT(new_snapshot, '$.phone') is not null)。
    • 流水表按business_typeoperation_time分区(如MySQL分区表),避免单表数据量过大影响查询性能。
    • 非核心链路可异步记录流水(如用消息队列),但需确保最终一致性(如失败重试)。
  2. 敏感信息脱敏
    若快照包含手机号、身份证等超敏感信息,可在存储前脱敏(如手机号只存前3后4位:138****5678),但需注意——脱敏后可能无法满足“完整追溯”需求,需在合规要求中权衡。

  3. 新增/删除操作

    • 新增(INSERT):old_snapshotnullnew_snapshot记录初始敏感字段。
    • 删除(DELETE):new_snapshotnullold_snapshot记录删除前的敏感字段。

总结

对于敏感信息的安全合规需求,“流水表+快照”模式是比AOP实时对比更直接、更可靠的方案。它通过持久化存储变更历史,确保每一次敏感操作都有迹可循,且通过注解和通用服务实现低侵入性,适合在电商、金融、社交等对合规性要求高的系统中落地。

参考资料

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/952004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode launch.json debug 带caffe库的工程代码

{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations&q…

PADS丨出 gerber 通用教程

目录一、出 gerber 通用教程二、出 gerber 常见问题 一、出 gerber 通用教程将原点设置在板子左下角。输入无模命令“@camdocs”或者选择“文件 --> CAM --> 自动定义”。将所有电气层(即所使用的2层 4层 6层 8…

jmeter阶梯试压测

插件:jmeterplungins-standard.jar放到jmeter安装目录\lib\ext路径下,重启jmeter启动jmeter 添加线程组jp@gc-Stepping Thread GroupThis group wil start 100 threads:设置线程组启动的线程总数为100个; First,wait…

实用指南:UNIX下C语言编程与实践20-UNIX 文件类型判断:stat 结构 st_mode 与文件类型宏的使用实战

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

uni-app x开发商城系统,社区图片,左侧结构样式,数据渲染,点击高亮

一、概述 上一篇文章,已经实现了联系我们,地图显示,拨打电话。 接下来,实现社区图片,左侧结构样式,效果如下: 二、scroll-view 可滚动视图区域。用于区域滚动。 官方文档:https://uniapp.dcloud.net.cn/compon…

Nginx的请求处理

本文分享自天翼云开发者社区《Nginx的请求处理》.作者:小谢不用谢 Nginx的请求处理流程worker进程中,ngx_worker_process_cycle()函数就是这个无限循环的处理函数。在这个函数中,一个请求的简单处理流程如下:(1)…

2025年液相色谱仪口碑推荐优质厂家,国产仪器品牌哪家强?

在当今科技飞速发展的时代,液相色谱仪作为分析检测领域的重要工具,其质量和性能对于科研、制药、环境监测等众多行业至关重要。2025年,市场上液相色谱仪品牌众多,而国产仪器品牌也在不断崛起,其中北京普析通用仪器…

【MySQL】数据库基础 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

云湖+小马算力:无需懂技术,轻松知识库AI智能机器人

注册小马算力:https://www.tokenpony.cn/3N6Rdu3e 注册完毕进入后台开通API keys在云湖APP中,创建机器人点击【机器人设置】开启大模型机器人选项,模型类型选择其他模型可以访问:https://www.tokenpony.cn/#/model…

2025年深圳geo优化服务公司权威推荐榜单:geo优化公司/geo优化推广/ai排名优化源头公司精选

在当前AI技术快速发展的背景下,生成式引擎优化(GEO)已成为企业获取AI搜索流量的核心手段。据行业数据显示,2025年全球AI搜索用户规模已突破8亿,超过60%的搜索请求会触发AI摘要回答,未能被AI采纳内容的品牌将面临…

2025年架空电缆源头厂家权威推荐榜单:屏蔽电缆/防火电缆/矿物质电缆源头厂家精选

随着全球电力网络升级与新能源并网需求激增,2025年架空电缆市场正迎来技术升级与产能扩张的双重浪潮。高质量架空电缆已成为保障电网安全、提升输电效率的核心要素。 架空电缆作为电力传输的"空中动脉",其…

hello-gui

hello-guiimport("stdfaust.lib"); ctFreq = hslider("[0]cutoffFrequency",500,50,10000,0.01) hslider 的第一个参数是参数的名称,因为它将在界面中显示或在API中使用(它可以不同于与UI元素关…

异常的处理

新版本的C#支持nullable功能,如果一个可空的对象,没有进行空值判断的话,IDE会有报警提示。 借助下面的一些特性标识,能够进行null值的判断。 对函数内引用的属性进行异常判断 通过ArgumentNullException.ThrowIfNu…

银河麒麟服务器操作系统 V10 (Lance) 安装docker 28

银河麒麟服务器操作系统 V10 (Lance) 安装docker 28银河麒麟服务器操作系统 V10 (Lance) 安装docker 28 编辑 复制银河麒麟服务器操作系统 V10 Docker安装 在银河麒麟服务器操作系统 V10 (Lance) 上安装 Docker 28.0.1…

Python创建类(下)_ 当上帝的时刻到了

Python创建类(下)_ 当上帝的时刻到了class Student: def __init__(self, name, student_id): self.name = name self.student_id = student_id self.grades = {"语文": 0, "…

超纯水售后哪家好?国产仪器权威推荐品牌top2

在科学研究和工业生产中,超纯水作为关键的基础资源,其质量和供应稳定性至关重要。选择一家售后服务优质的超纯水设备供应商,不仅能确保设备的长期稳定运行,还能为科研和生产提供有力保障。本文将基于国产仪器领域的…

PADS丨极坐标设置

在需要布局的位置设置原点。使用无模命令“GP”打开极坐标栅格。打开 设置 -> 栅格 -> 径向移动设置 -> 设置半径和环的数量。选中元器件 -> 右键选择“径向移动”,即可按极坐标布局。元器件换方向 ->…

题解:P11630 [WC2025] 士兵

更差的阅读体验考虑一个很菜的 dp。假设 \(f_{i, j}\) 表示前 \(i\) 个人,对着 \(i\) 砍了 \(j\) 刀的方案数。那么很显然有转移: \[f_{i, j} = \max_{k} \{f_{i-1, k} - m \times \max(0, j-k)\} + [j \ge a_i] \ti…

2025 年 SMT 加工优质厂家最新推荐榜,技术实力与市场口碑深度解析的权威甄选结果

引言 2025 年 SMT 加工行业竞争愈发激烈,为助力企业精准选择合作厂家,电子制造协会联合国内权威测评机构开展专项测评。本次测评历时 3 个月,覆盖珠三角、长三角等核心电子制造产业带超 200 家 SMT 加工企业,采用 …

Oracle 19c数据库迁移到IvorySQL 4.6实战

1. 背景 在国家数字化转型与信创产业加速推进的背景下,数据库作为信息系统的核心基础设施,其国产化替代已成为企业数字化建设的重要战略方向。Oracle 数据库凭借成熟的技术体系长期占据市场主导地位,但在自主可控、…