1. 前言
在我们日常开发系统的安全架构中,仅仅通过认证和授权往往不足以满足合规、溯源、风险预警等需求。企业级系统必须记录并分析 “谁在什么时候对什么资源做了什么操作”,并结合规则引擎识别异常行为,及时告警。
安全审计作为企业防护的最后一道防线,能有效追踪异常行为、还原攻击链、满足合规要求。本文笔者将带领大家基于 Spring Security 构建完整的安全审计系统,实现关键操作追踪与实时风险预警。
2. Spring Security 审计架构设计
2.1 系统架构
我们常见的安全审计应该具备以下基础:以笔者目前所在公司使用的系统架构如下图:

2.2 审计日志四要素
| 要素 |
说明 |
示例 |
| 主体 |
操作执行者 |
用户 ID、IP 地址 |
| 客体 |
被操作对象 |
数据 ID、接口路径 |
| 动作 |
操作类型 |
登录、删除、授权变更 |
| 环境 |
操作上下文 |
时间、设备、地理位置 |
2.3 技术栈选择
- 事件采集:Spring AOP + ApplicationEvent
- 存储方案:MySQL + MyBatis‑Plus(中小型应用适用)或 Elasticsearch + Logstash(大型应用 + 实时检索)
- 风险分析:Drools 规则引擎
- 可视化:Grafana 监控看板
笔者为简化演示,本文以 MySQL + MyBatis‑Plus 为存储方案。
鉴于之前的子模块代码中,我们已经集成好了 MySQL + MyBatis‑Plus,在开始之前复用之前的子模块,需在 pom.xml 中引入:
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>9.44.0.Final</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-spring</artifactId> <version>7.74.1.Final</version> </dependency>
|
3. 数据库与实体设计
1 2 3 4 5 6 7 8
| CREATE TABLE audit_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50), action VARCHAR(100), resource VARCHAR(200), timestamp DATETIME, duration BIGINT );
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Data @TableName("audit_log") public class AuditLog { @TableId(type = IdType.AUTO) private Long id; private String username; private String action; private String resource; private LocalDateTime timestamp; private Long duration; }
@Mapper public interface AuditLogMapper extends BaseMapper<AuditLog> {}
|
4. 事件采集:Spring AOP + 自定义注解
4.1 自定义注解
1 2 3 4 5 6
| @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Audit { String action(); String resource(); }
|
4.2 AOP 切面实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Aspect @Component public class AuditAspect { @Autowired private ApplicationEventPublisher publisher;
@Pointcut("@annotation(audit)") public void auditPoint(Audit audit) {}
@Around("auditPoint(audit)") public Object around(ProceedingJoinPoint jp, Audit audit) throws Throwable { long start = System.currentTimeMillis(); Object result = jp.proceed(); long duration = System.currentTimeMillis() - start;
MethodSignature ms = (MethodSignature) jp.getSignature(); String username = ((UserDetails) SecurityContextHolder.getContext() .getAuthentication().getPrincipal()).getUsername();
AuditEvent evt = new AuditEvent(username, audit.action(), audit.resource(), duration, LocalDateTime.now()); publisher.publishEvent(evt); return result; } }
|
说明:上述代码中,可补充捕获异常并发布失败事件。
4.3 事件类
1 2 3
| public record AuditEvent(String username, String action, String resource, long duration, LocalDateTime timestamp) {}
|
4.4 事件监听并保存日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Component @RequiredArgsConstructor public class AuditListener { private final AuditLogMapper mapper; private final KieContainer kieContainer; private final Counter riskCounter;
@EventListener public void handle(AuditEvent evt) { AuditLog log = new AuditLog(null, evt.username(), evt.action(), evt.resource(), evt.timestamp(), evt.duration()); mapper.insert(log);
var session = kieContainer.newKieSession(); session.insert(log); var fired = session.fireAllRules(); session.dispose();
if (fired > 0) riskCounter.increment(); } }
|
5. Drools 动态规则引擎
5.1 Drools 配置
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration public class DroolsConfig { @Bean public KieContainer kieContainer() { KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write(ResourceFactory.newClassPathResource("rules/audit-risk.drl")); ks.newKieBuilder(kfs).buildAll(); return ks.newKieContainer( ks.getRepository().getDefaultReleaseId()); } }
|
5.2 规则文件 audit-risk.drl
1 2 3 4 5 6
| rule "Slow Audit" when $log: AuditLog(duration > 1000) then System.out.println("风险预警:操作耗时过长 by " + $log.getUsername()); end
|
6. 监控指标采集与可视化
6.1 添加监控依赖并启用 Actuator
1 2 3 4 5 6 7 8
| <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
|
6.2 配置 application.yml
1 2 3 4 5
| management: endpoints: web: exposure: include: prometheus,health
|
6.3 指标配置
1 2 3 4 5 6 7 8 9
| @Configuration public class MetricsConfig { @Bean public Counter riskCounter(MeterRegistry reg) { return Counter.builder("audit.risk.count") .description("Number of risky audit events") .register(reg); } }
|
Prometheus 采集 /actuator/prometheus,Grafana 仪表板配置查询:audit_risk_count。
7. 控制器示例
完成上述所有操作后,可编写一个 Controller 进行相关测试:
1 2 3 4 5 6 7 8 9 10
| @RestController @RequestMapping("/api") @RequiredArgsConstructor public class DemoController { @Audit(action = "ACCESS", resource = "demoEndpoint") @GetMapping("/demo") public String demo() { return "OK"; } }
|
8. 结语
本章节我们以最简单的一个入门示例,主要讲解了:
- 利用 MyBatis‑Plus 实现高效、自动化地操作 MySQL 审计日志表;
- 通过 Spring AOP + ApplicationEvent 实现操作日志透明采集;
- 使用 Drools 规则引擎实现可配置、实时化的风险判断;
- 集成 Prometheus + Grafana 实现可视化监控,从流量、耗时、风险事件维度全方位审计系统行为。
这套方案可按需扩展为审计超级系统,支持敏感操作追踪、异常报警、人机判定等功能,适合企业级复杂场景。后续可添加 CI/CD 自动部署 Drools 规则、Grafana 警报等高级功能。
如果你在实践过程中有任何疑问或更好的扩展思路,欢迎在评论区留言,最后希望大家 一键三连 给笔者一点点鼓励!