- 后端
- 认证鉴权
- 单点登录
【免费下载链接】cas
Apereo CAS - Identity & Single Sign On for all earthlings and beyond.
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 继承自Slf4jLoggingAuditTrailManager(org.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.groovytemplate.location支持 Spring 资源定位语法:
file:/path/to/GroovyAudit.groovy:引用文件系统路径;classpath:/GroovyAudit.groovy:引用 classpath 下的资源(测试用例即采用此方式,见下文)。
在 CasCoreAuditAutoConfiguration 中,配置装配逻辑如下:
- 通过
BeanCondition.on("cas.audit.groovy.template.location").exists()判断是否定义了该属性——只要配置了template.location,Groovy 审计管理器就会被注册到审计执行计划中; - 注册的 Bean 名为
casGroovyAuditTrailExecutionPlanConfigurer,带@RefreshScope,意味着模板位置变更可以通过配置刷新热生效; - 被
@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_CREATED、AUTHENTICATION_SUCCESS)。 |
userAgent | 客户端浏览器/用户代理字符串。 |
application | 应用代码/来源标识。 |
geoLocation | 客户端地理位置信息(若配置了地理位置服务)。 |
| HTTP 请求头 | 收集到的所有请求头按各自名称传入,例如customHttpRequestHeader。 |
| Extra Info | 审计引擎从各组件收集的任意键/值附加信息。 |
这些参数的来源可以从 AbstractStringAuditTrailManager.getMappedAuditActionContext 中逐一印证:who、what、action、application、when、clientIpAddress、serverIpAddress、userAgent、headers、geoLocation、deviceFingerprint、tenant等均来自AuditActionContext及其携带的ClientInfo对象;HTTP 请求头与附加信息则来自ClientInfo.getHeaders()与getExtraInfo()。
编写 Groovy 审计模板
最小示例
原文档给出的示例脚本如下:
${logger.info("Hello, World")} who: ${who}, what: ${what}, when: ${when}, ip: ${clientIpAddress}, trace: ${customHttpRequestHeader}该模板展示了两个要点:
${...}为模板占位符语法,在渲染时会被替换为对应参数的值;- 模板可以直接调用
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 揭示了完整的渲染流水线:
- 收集上下文:把
ClientInfo的 HTTP 请求头(getHeaders())与附加信息(getExtraInfo())合并进一个HashMap; - 叠加审计字段:通过
getMappedAuditActionContext(...)注入who/what/action/application/when/clientIpAddress/serverIpAddress/userAgent/headers/geoLocation等标准字段; - 注入基础设施:放入
applicationContext(Spring 应用上下文)与logger(即Slf4jLoggingAuditTrailManager的LOG实例); - 渲染模板:调用
ExecutableCompiledScriptFactory.createTemplate(groovyTemplate, map)以模板文件 + 上下文 Map 渲染出最终字符串; - 输出日志:由于继承自
Slf4jLoggingAuditTrailManager,渲染结果通过LOG.info(...)输出到 CAS 的审计日志。
因此,你在脚本中见到的每一个${...}占位符,本质上都是从这个上下文Map中按名字取值;而applicationContext与logger两个对象是框架额外注入的"特权"参数,这正是模板既能查 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: casuser、what: TEST、when: ...、ip: 1.2.3.4等字段。
这个测试同时证明:ClientInfo的 headers 与 extra info 会被合入模板上下文,因此"任意 HTTP 请求头按名引用"与"Extra Info 按名引用"在实现上是成立的。
实践建议与注意事项
- 模板位置:生产环境建议使用
file:指向外部文件系统,便于运维在不重新打包 WAR 的情况下修改审计格式;改动后利用@RefreshScope通过配置刷新生效。 - 日志级别:审计记录以
INFO输出,而模板内的logger.debug(...)只会在 DEBUG 级别可见,合理利用级别区分"审计正文"与"调试辅助信息"。 - 字段可裁剪:
AbstractStringAuditTrailManager支持auditableFields(AuditableFields枚举集合)裁剪注入的字段,若不需要地理位置等字段,可通过相应配置减少上下文体积(空集合表示输出全部字段)。 - GraalVM 限制:Groovy 审计管理器被
@ConditionalOnMissingGraalVMNativeImage修饰,在 Native Image 运行模式下不会被装配,部署时需留意该前提。 - 故障排查:脚本中的 Groovy 语法错误会在渲染阶段抛出并被
FunctionUtils.doUnchecked包装为运行时异常,可关注 CAS 审计相关日志定位模板问题;修改模板后建议先用少量请求验证输出格式,再全量放开。
- 后端
- 认证鉴权
- 单点登录
【免费下载链接】cas
Apereo CAS - Identity & Single Sign On for all earthlings and beyond.
相关推荐
Apereo CAS 文件型审计(File-based Audits)实践:cas_audit.log 输出配置与源码实现解析
Apereo CAS 文件型审计(File based Audits)实践:cas_audit.log 输出配置与源码实现解析 导读 Apereo CAS 的审
后端认证鉴权单点登录Apache Groovy数据库操作:Groovy SQL模块完全解析
Apache Groovy数据库操作:Groovy SQL模块完全解析 Apache Groovy SQL模块是JVM平台上最强大的数据库操作工具之一,为开发者
编程语言编译器语言运行时Spring Framework中的Groovy Markup模板引擎解析
Spring Framework中的Groovy Markup模板引擎解析 什么是Groovy Markup模板引擎 Groovy Markup Templat
后端Web框架依赖注入
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考