news 2026/9/23 18:44:52

Apereo CAS Groovy 审计(Groovy Audits):用 Groovy 模板完全定制审计记录的输出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apereo CAS Groovy 审计(Groovy Audits):用 Groovy 模板完全定制审计记录的输出
  • 后端
  • 认证鉴权
  • 单点登录

【免费下载链接】cas

Apereo CAS - Identity & Single Sign On for all earthlings and beyond.

项目地址:https://gitcode.com/gh_mirrors/ca/cas
点击查看免费下载

Apereo CAS 内置了多种审计(Audit)记录实现,其中 Groovy 审计是灵活性最高的一种:它允许通过一段 Groovy 模板脚本来接收审计上下文中的全部参数(操作者、被操作资源、时间、IP、HTTP 请求头、自定义附加信息等),并按任意文本格式拼装最终的审计记录,再交给日志框架以INFO级别输出。读完本文,你将掌握如何启用cas.audit.groovy配置、编写可用的 Groovy 审计模板、理解脚本各参数的来源与含义,并从源码与测试用例层面洞悉该功能的底层实现原理。

什么是 Groovy 审计

在 CAS 中,每次登录、登出、票据颁发等关键动作都会产生一个可审计的事件上下文(AuditActionContext),审计记录管理器(AuditTrailManager)负责把这些上下文转换成可持久化、可检索的记录。默认情况下,CAS 使用内置的文本/JSON 格式化器输出固定格式的日志;而Groovy 审计则把"格式化"这一步完全交给用户自定义的 Groovy 脚本:

  • 脚本可以访问审计引擎收集到的全部上下文参数;
  • 输出格式完全由脚本决定,可以是纯文本、JSON、CSV 或任何你想要的表示形式;
  • 最终生成的审计记录会被交给日志框架,通常以INFO级别记录(Slf4jLoggingAuditTrailManager 中的record方法直接调用LOG.info(toString(auditActionContext)))。

从源码结构看,GroovyAuditTrailManager 继承自Slf4jLoggingAuditTrailManagerorg.apereo.inspektr.audit.support包,自 7.0.0 版本起提供),因此它本质上是"日志型审计管理器 + Groovy 模板渲染器"的组合。

前置条件:启用 Apache Groovy 脚本支持

在使用 Groovy 审计之前,需要确保 CAS 运行环境已集成 Apache Groovy 脚本引擎。CAS 对 Groovy 脚本能力的整体说明(包括如何引入依赖、脚本引擎如何被复用)见 Apache-Groovy-Scripting 指南。模板渲染在运行时通过ExecutableCompiledScriptFactory完成(见下文源码分析),因此该模块是 Groovy 审计的硬性依赖。

配置 Groovy 审计

Groovy 审计的配置前缀为cas.audit.groovy,配置模型定义在 AuditGroovyProperties 中,标注了@RequiresModule(name = "cas-server-core-audit"),即该功能随cas-server-core-audit模块提供。

该配置仅有一个嵌套属性template(类型为SpringResourceProperties),用于指向构造审计记录的 Groovy 模板文件。一个典型的application.yml配置如下:

cas: audit: groovy: template: location: file:/etc/cas/config/audit/GroovyAudit.groovy

template.location支持 Spring 资源定位语法:

  • file:/path/to/GroovyAudit.groovy:引用文件系统路径;
  • classpath:/GroovyAudit.groovy:引用 classpath 下的资源(测试用例即采用此方式,见下文)。

在 CasCoreAuditAutoConfiguration 中,配置装配逻辑如下:

  1. 通过BeanCondition.on("cas.audit.groovy.template.location").exists()判断是否定义了该属性——只要配置了template.location,Groovy 审计管理器就会被注册到审计执行计划中
  2. 注册的 Bean 名为casGroovyAuditTrailExecutionPlanConfigurer,带@RefreshScope,意味着模板位置变更可以通过配置刷新热生效;
  3. @ConditionalOnMissingGraalVMNativeImage修饰,说明该特性在当前版本的 GraalVM Native Image 编译场景下不受支持(这是运行时环境的适用前提)。

注意:Groovy 审计管理器被注册后会参与审计执行计划,与cas.audit.slf4j等日志型审计可以共存。若只想保留 Groovy 审计,可像测试用例那样将cas.audit.slf4j.enabled=false关闭其他输出(见 GroovyAuditTrailManagerTests)。

脚本可用的参数

当每次审计记录被触发时,CAS 会把以下参数绑定到 Groovy 模板的上下文中:

参数说明
applicationContext代表 Spring 应用上下文的对象(ApplicationContext),可在脚本中按需获取任意 Bean。
logger负责输出日志消息的对象,例如logger.info(...)logger.debug(...)
clientIpAddress客户端 IP 地址。
serverIpAddress服务端 IP 地址。
what被操作/被访问的资源(例如目标服务 URL 或票据 ID)。
who执行操作的主体(通常是认证后的 principal)。
when操作发生的时间。
action执行的动作(例如TICKET_GRANTING_TICKET_CREATEDAUTHENTICATION_SUCCESS)。
userAgent客户端浏览器/用户代理字符串。
application应用代码/来源标识。
geoLocation客户端地理位置信息(若配置了地理位置服务)。
HTTP 请求头收集到的所有请求头按各自名称传入,例如customHttpRequestHeader
Extra Info审计引擎从各组件收集的任意键/值附加信息。

这些参数的来源可以从 AbstractStringAuditTrailManager.getMappedAuditActionContext 中逐一印证:whowhatactionapplicationwhenclientIpAddressserverIpAddressuserAgentheadersgeoLocationdeviceFingerprinttenant等均来自AuditActionContext及其携带的ClientInfo对象;HTTP 请求头与附加信息则来自ClientInfo.getHeaders()getExtraInfo()

编写 Groovy 审计模板

最小示例

原文档给出的示例脚本如下:

${logger.info("Hello, World")} who: ${who}, what: ${what}, when: ${when}, ip: ${clientIpAddress}, trace: ${customHttpRequestHeader}

该模板展示了两个要点:

  1. ${...}为模板占位符语法,在渲染时会被替换为对应参数的值;
  2. 模板可以直接调用logger输出额外的日志,也可以引用任意 HTTP 请求头(此处以名为customHttpRequestHeader的请求头为例)。

从测试资源看更丰富的用法

仓库测试资源中提供了一个更完整的真实模板 GroovyAudit.groovy,演示了在脚本中获取 Spring Bean 的姿势:

${logger.info("Groovy audit manager running...")} ${ def bean = applicationContext.getBean(org.apereo.cas.audit.AuditTrailExecutionPlan.BEAN_NAME) logger.debug(bean.class.name) } who: ${who}, what: ${what}, when: ${when}, ip: ${clientIpAddress}

从中可以学到的进阶技巧:

  • 通过applicationContext.getBean(...)在模板中按需访问 CAS 内部 Bean(例如审计执行计划AuditTrailExecutionPlan),从而实现动态、可编程的审计记录生成;
  • 多行${...}代码块可以包含任意 Groovy 逻辑(声明变量、调用方法、循环等),模板本质上是一段可执行的 Groovy 脚本片段;
  • 模板中声明的变量、打印的输出与占位符混排,最终字符串即为审计记录内容。

由于渲染是"先把整个模板渲染为字符串、再交给日志框架输出",你完全可以在此字符串中拼装 JSON:

${logger.debug("Building JSON audit record")} {"who": "${who}", "what": "${what}", "when": "${when}", "clientIp": "${clientIpAddress}", "action": "${action}"}

底层实现原理

GroovyAuditTrailManager.toString 揭示了完整的渲染流水线:

  1. 收集上下文:把ClientInfo的 HTTP 请求头(getHeaders())与附加信息(getExtraInfo())合并进一个HashMap
  2. 叠加审计字段:通过getMappedAuditActionContext(...)注入who/what/action/application/when/clientIpAddress/serverIpAddress/userAgent/headers/geoLocation等标准字段;
  3. 注入基础设施:放入applicationContext(Spring 应用上下文)与logger(即Slf4jLoggingAuditTrailManagerLOG实例);
  4. 渲染模板:调用ExecutableCompiledScriptFactory.createTemplate(groovyTemplate, map)以模板文件 + 上下文 Map 渲染出最终字符串;
  5. 输出日志:由于继承自Slf4jLoggingAuditTrailManager,渲染结果通过LOG.info(...)输出到 CAS 的审计日志。

因此,你在脚本中见到的每一个${...}占位符,本质上都是从这个上下文Map中按名字取值;而applicationContextlogger两个对象是框架额外注入的"特权"参数,这正是模板既能查 Spring Bean、又能直接打日志的原因。

用测试用例验证行为

GroovyAuditTrailManagerTests 是该功能的单元级验证,展示了完整的使用姿势:

  • 测试配置了cas.audit.groovy.template.location=classpath:/GroovyAudit.groovy,并关闭cas.audit.slf4j.enabled
  • 测试构造了一个AuditActionContext,携带 principal(casuser)、动作(TEST)、资源(TEST)、应用码(CAS)、时间以及ClientInfo(IP 为1.2.3.4,附加信息Hello -> World,请求头H1 -> V1);
  • 调用auditTrailManager.record(ctx)后,模板会被渲染并通过INFO日志输出,日志中应能看到who: casuserwhat: TESTwhen: ...ip: 1.2.3.4等字段。

这个测试同时证明:ClientInfo的 headers 与 extra info 会被合入模板上下文,因此"任意 HTTP 请求头按名引用"与"Extra Info 按名引用"在实现上是成立的。

实践建议与注意事项

  1. 模板位置:生产环境建议使用file:指向外部文件系统,便于运维在不重新打包 WAR 的情况下修改审计格式;改动后利用@RefreshScope通过配置刷新生效。
  2. 日志级别:审计记录以INFO输出,而模板内的logger.debug(...)只会在 DEBUG 级别可见,合理利用级别区分"审计正文"与"调试辅助信息"。
  3. 字段可裁剪AbstractStringAuditTrailManager支持auditableFieldsAuditableFields枚举集合)裁剪注入的字段,若不需要地理位置等字段,可通过相应配置减少上下文体积(空集合表示输出全部字段)。
  4. GraalVM 限制:Groovy 审计管理器被@ConditionalOnMissingGraalVMNativeImage修饰,在 Native Image 运行模式下不会被装配,部署时需留意该前提。
  5. 故障排查:脚本中的 Groovy 语法错误会在渲染阶段抛出并被FunctionUtils.doUnchecked包装为运行时异常,可关注 CAS 审计相关日志定位模板问题;修改模板后建议先用少量请求验证输出格式,再全量放开。
  • 后端
  • 认证鉴权
  • 单点登录

【免费下载链接】cas

Apereo CAS - Identity & Single Sign On for all earthlings and beyond.

项目地址:https://gitcode.com/gh_mirrors/ca/cas
点击查看免费下载
上一篇:突破硬件限制:OpenCore Legacy Patcher企业级部署指南
下一篇:终极指南:如何使用Universal Android Debloater彻底移除Simple Mobile Tools应用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 18:44:23

Unity3D运行时OBJ模型导入与碰撞体生成完整实现

简介:面向Unity开发者的运行时模型处理源码工程,解决在游戏运行阶段动态导入外部模型文件、实时编辑其位置、旋转、缩放及碰撞体信息并持久化保存的完整需求。工程整合TriLib模型加载插件与RuntimeTransformGizmos操作插件,同时提供数值输入面…

作者头像 李华
网站建设 2026/9/23 18:43:31

Dart SDK 中 FFI 基准测试原生库的构建与 CIPD 发布流程指南

编程语言编译器语言运行时标准库开发工具 【免费下载链接】sdk The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more. 项目地址: https://gitcode.com/gh_mirrors/sdk1/sdk 点击查看 免费下载 本文以 Dart SDK 仓库中的 b…

作者头像 李华
网站建设 2026/9/23 18:43:07

高分遥感语义分割实战:PyTorch实现地物分类与面积估算全流程

简介:这是一份面向遥感与计算机视觉学习者的项目实践资源,以PyTorch为基础实现高分遥感影像语义分割,解决地物分类任务。资源基于GF2影像样本数据,覆盖模型设计、数据加载、训练验证与推理预测全流程,并重点展开膨胀预…

作者头像 李华
网站建设 2026/9/23 18:42:16

G6 节点(Node)体系全解析:内置类型、数据结构与样式配置实战

数据可视化前端图表库 【免费下载链接】G6 ♾ A Graph Visualization Framework in JavaScript. 项目地址: https://gitcode.com/gh_mirrors/g6/G6 点击查看 免费下载 节点是图可视化中最核心的构成单元。本文以 G6 官方文档《节点总览》为主线,结合 G6…

作者头像 李华
网站建设 2026/9/23 18:41:14

BUCK电路环路补偿设计与Saber仿真验证:从传递函数到相位裕量

简介:这是一份面向开关电源研发工程师的环路设计专题资料,聚焦BUCK电路从环路计算、补偿参数设计到仿真验证的完整流程。资料从自动控制理论中的乃奎斯特稳定性判据切入,讲解穿越频率、相位裕量、增益裕量、静态增益与动态响应等关键概念&…

作者头像 李华
网站建设 2026/9/23 18:40:21

单通道脑电睡眠分期实战:Python从EDF到分类模型

简介:这份资源面向计算机、人工智能、通信工程、自动化、电子信息等专业的在校学生与教师,以及希望入门生理信号处理的企业员工,提供一套基于单通道脑电信号实现自动睡眠分期的完整Python项目。项目围绕EEG信号预处理、数据集构建、深度网络建…

作者头像 李华