ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apereo CAS 基于 Groovy 脚本的灵活认证(Groovy Authentication)实战指南

Apereo CAS 基于 Groovy 脚本的灵活认证(Groovy Authentication)实战指南 Apereo CAS 基于 Groovy 脚本的灵活认证Groovy Authentication实战指南【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址: https://gitcode.com/gh_mirrors/ca/cas导读本文介绍 Apereo CAS 中一种高度灵活的认证方式——Groovy Authentication将用户名/密码等凭证的校验逻辑完全交由外部 Groovy 脚本实现CAS 只负责调度与结果装配。借助这种方式可以在不修改 Java 代码、不重新构建 WAR 的情况下随时调整认证策略、快速接入遗留系统或试验性认证方案。读完本文你将掌握如何引入cas-server-support-generic模块、如何配置cas.authn.groovy.*属性、如何编写符合 CAS 调用契约的 Groovy 脚本并理解其背后的源码实现与热加载机制。一、Groovy 认证的工作原理Groovy 认证对应仓库文档 Groovy-Authentication.md的核心思想是凭证校验、Principal 转换、密码策略处理以及其他一切相关事项全部由 Groovy 脚本全权负责。CAS 不再关心“密码是否正确”这类业务细节只负责将待认证的Credential如UsernamePasswordCredential以及认证上下文ServicesManager、PrincipalFactory、日志器作为参数传给脚本调用脚本中的authenticate方法完成校验若脚本返回DefaultAuthenticationHandlerExecutionResult则认证成功并进入后续 Principal 解析与票据签发流程若脚本抛出FailedLoginException则认证失败。从源码结构看该功能被设计为通用的AuthenticationHandler实现详见下文“源码级解析”因此它可以无缝接入 CAS 既有的认证事件执行计划Authentication Event Execution Plan与 JDBC、LDAP 等其他认证处理器并行工作、按order排序。二、启用模块依赖支持 Groovy 认证的模块是cas-server-support-generic。在 WAR overlay 项目的build.gradle中引入implementation org.apereo.cas:cas-server-support-generic该模块位于仓库 support/cas-server-support-generic内部既包含 Groovy 认证处理器也包含文件File、拒绝Reject、Shiro 等通用认证处理器。提示若你的脚本中还需要使用 Apache Groovy 的更多脚本化能力如内联脚本、CompileStatic静态编译建议同时参阅 Apache-Groovy-Scripting.md其中说明需要引入cas-server-core-scripting模块否则 Groovy 相关类库不会被拉入 CAS 运行时。三、配置项说明cas.authn.groovy.*在application.properties/application.yml或 CAS 配置服务中通过cas.authn.groovy前缀完成配置。其绑定模型对应源码 GroovyAuthenticationProperties.java并继承自 SpringResourceProperties.java。配置键类型默认值说明cas.authn.groovy.locationResource无必填Groovy 脚本位置。可以是文件系统路径、classpath:资源或 URL。该配置存在时才会激活 Groovy 认证处理器见源码BeanCondition.on(cas.authn.groovy.location).exists()cas.authn.groovy.nameString无认证处理器的名称用于在日志、审计与认证执行计划中标识该处理器cas.authn.groovy.orderInteger无处理器在认证链中的执行顺序数值越小优先级越高cas.authn.groovy.stateAuthenticationHandlerStatesACTIVE处理器的作用域与生命周期状态如激活/停用默认ACTIVE典型配置示例properties 形式cas.authn.groovy.locationfile:/etc/cas/config/GroovyAuthnHandler.groovy cas.authn.groovy.nameGroovyAuthnHandler cas.authn.groovy.order10 cas.authn.groovy.stateACTIVE关于location还有两点来自 SpringResourceProperties.java 的实践提醒inotify 限制如果脚本被设置为随变更自动重载CAS 默认会监视资源变化在 Linux 上可能需要调大 inotify 实例上限。可在/etc/sysctl.conf中增加fs.inotify.max_user_instances 256并通过cat /proc/sys/fs/inotify/max_user_instances查看当前值。关闭资源监视如需禁用底层资源监视器可设置系统属性或环境变量org.apereo.cas.util.io.PathWatcherServicefalse。四、编写 Groovy 认证脚本方法契约脚本是 Groovy 认证的核心。CAS 会在运行时按固定方法名、固定参数个数调用脚本详见第五节源码解析因此脚本必须实现以下三个方法。1.authenticate(...)执行凭证校验import org.apereo.cas.authentication.* import org.apereo.cas.authentication.credential.* import org.apereo.cas.authentication.metadata.* import javax.security.auth.login.* def authenticate(final Object... args) { def (authenticationHandler, credential, servicesManager, principalFactory, logger) args /* * Figure out how to verify credentials... */ if (authenticationWorksCorrectly()) { def principal principalFactory.createPrincipal(credential.username); return new DefaultAuthenticationHandlerExecutionResult(authenticationHandler, credential, principal, new ArrayList()); } throw new FailedLoginException(); }参数绑定共 5 个按序传入authenticationHandler当前处理器实例、credential待认证凭证、servicesManager服务管理器、principalFactoryPrincipal 工厂、loggerCAS 日志器。成功路径调用principalFactory.createPrincipal(username)构造 Principal并封装为DefaultAuthenticationHandlerExecutionResult返回。失败路径抛出javax.security.auth.login.FailedLoginExceptionCAS 会将其视为认证失败。扩展DefaultAuthenticationHandlerExecutionResult的构造器还支持传入ListMessageDescriptor认证警告信息可用来向登录流程附加提示。2.supportsCredential(...)判断是否支持给定凭证实例def supportsCredential(final Object... args) { def (credential, logger) args return credential ! null }参数绑定共 2 个credential凭证实例、logger。返回值true表示该处理器接受此凭证实例。示例中只要凭证非空即支持。3.supportsCredentialClass(...)判断是否支持给定凭证类型def supportsCredentialClass(final Object... args) { def (credentialClazz, logger) args return credentialClazz UsernamePasswordCredential.class }参数绑定共 2 个credentialClazz凭证的Class对象、logger。返回值true表示处理器支持该类型凭证。示例限定仅支持UsernamePasswordCredential用户名密码凭证。注意Groovy 闭包参数解构def (a, b, c) args依赖脚本接收可变参数Object... args这与 CAS 通过watchableScript.execute(methodName, ReturnType.class, args)反射式调用的方式对应。你也可以像仓库测试脚本那样按索引取参def credential args[1]。五、源码级解析处理器与注册机制1. 处理器实现核心类是 GroovyAuthenticationHandler.java自 CAS 6.1.0 引入继承自AbstractAuthenticationHandler构造时通过ExecutableCompiledScriptFactory.getExecutableCompiledScriptFactory().fromResource(groovyResource)将脚本资源编译为可执行脚本对象watchableScript该对象支持按需重载authenticate(credential, service)组装 5 元参数数组{this, credential, servicesManager, getPrincipalFactory(), LOGGER}调用脚本的authenticate方法期望返回AuthenticationHandlerExecutionResultsupports(Credential)组装 2 元参数{credential, LOGGER}调用脚本的supportsCredentialsupports(Class? extends Credential)组装 2 元参数{clazz, LOGGER}调用脚本的supportsCredentialClass。这解释了脚本方法签名为何是“方法名 可变参数”以及各参数的顺序与含义。2. 自动装配与条件激活GroovyAuthenticationEventExecutionPlanConfiguration.java 负责把处理器注册进认证执行计划使用ConditionalOnFeatureEnabled(feature Authentication, module generic)与ConditionalOnMissingGraalVMNativeImage控制生效条件通过BeanCondition.on(cas.authn.groovy.location).exists()判断只有配置了cas.authn.groovy.location才会真正创建GroovyAuthenticationHandlerBean创建处理器时读取groovy.getName()、groovy.getOrder()并注入groovyPrincipalFactory与servicesManager最后设置handler.setState(groovy.getState())groovyResourceAuthenticationEventExecutionPlanConfigurer在脚本位置非空时调用plan.registerAuthenticationHandlerWithPrincipalResolver(handler, defaultPrincipalResolver)将处理器与默认 Principal 解析器绑定。因此即使模块已引入未配置location时该处理器也不会被激活日志会输出Activating Groovy authentication handler via [...]说明激活情况。3. 测试用例佐证仓库单元测试 GroovyAuthenticationHandlerTests.java 使用类路径脚本GroovyAuthnHandler.groovy验证了完整调用链构造处理器 →supports(credential)返回 true →supports(UsernamePasswordCredential.class)返回 true →authenticate(...)返回非空结果。测试脚本 GroovyAuthnHandler.groovy 展示了一个可运行的完整范例——它校验“用户名等于密码”作为认证规则是一个很好的最小可运行参考import org.apereo.cas.authentication.DefaultAuthenticationHandlerExecutionResult import org.apereo.cas.authentication.credential.UsernamePasswordCredential import javax.security.auth.login.FailedLoginException def authenticate(final Object... args) { def authenticationHandler args[0] def credential args[1] def servicesManager args[2] def principalFactory args[3] def logger args[4] if (credential.username credential.toPassword()) { def principal principalFactory.createPrincipal(credential.username) return new DefaultAuthenticationHandlerExecutionResult(authenticationHandler, credential, principal, new ArrayList()) } throw new FailedLoginException() } def supportsCredential(final Object... args) { def credential args[0] def logger args[1] return credential ! null } def supportsCredentialClass(final Object... args) { def credentialClazz args[0] def logger args[1] return credentialClazz UsernamePasswordCredential.class }六、与 Groovy 脚本集成环境的衔接在开始编写脚本前建议先阅读 Apache-Groovy-Scripting.md它说明了 CAS 使用 Groovy 的两种形态外部脚本与内嵌脚本以及两个重要环境因素默认动态执行脚本默认通过 Groovy Meta Object Protocol 动态执行便于快速迭代静态编译模式如需开启类型检查可在启动 CAS 时设置系统属性-Dorg.apereo.cas.groovy.compile.statictrue。但注意开启后脚本中的动态构造如attributes[entitlement]这类动态索引可能需要改写为静态类型安全写法否则会编译失败。七、典型应用场景与注意事项典型场景快速验证新的认证规则无需重新构建 CAS 的 Java 代码对接数据格式特殊、难以用标准 LDAP/JDBC 查询表达的认证源在多个环境间共享一份可热更新的认证策略文件与 CAS 服务管理中的服务注册表配合实现按服务定制的认证行为。注意事项脚本异常要显式抛出FailedLoginException或返回失败语义避免静默吞掉异常导致认证流程行为不明确location指向的脚本应保证 CAS 运行用户可读若使用文件系统路径并期望热更新注意 inotify 上限见第三节supports系列方法决定了该处理器会被分派到哪些凭证多个认证处理器共存时请通过order明确执行顺序认证成功但 Principal 解析需要额外属性时可结合 Attribute-Resolution-Groovy.md 等属性解析方案在 Principal 基础上补充属性数据。八、小结Groovy Authentication 是 Apereo CAS 提供的一种“脚本即认证逻辑”的轻量扩展点通过cas-server-support-generic模块 cas.authn.groovy.*配置 三个约定方法authenticate/supportsCredential/supportsCredentialClass即可在无需编译 Java 代码的前提下灵活实现凭证校验。仓库中 GroovyAuthenticationHandler.java 与配套测试脚本提供了从配置到运行的完整闭环参考是理解 CAS 认证扩展机制的良好起点。【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址: https://gitcode.com/gh_mirrors/ca/cas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表