首页/新闻资讯/正文详情

Apereo CAS 自定义 Passwordless 认证用户账户存储(PasswordlessUserAccountStore)完整实现指南

发布时间:2026/9/26 2:03:48 来源:云帆数科 栏目:资讯中心
Apereo CAS 自定义 Passwordless 认证用户账户存储(PasswordlessUserAccountStore)完整实现指南
后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载导读本文聚焦 Apereo CAS 无密码Passwordless认证体系中用户账户存储这一核心扩展点讲解如何通过实现PasswordlessUserAccountStore接口、注册自定义 Spring Bean 来替换或扩展现有账户数据源。阅读本文后你将掌握PasswordlessUserAccountStore接口的定义与职责、CAS 默认提供的多种账户存储实现及加载机制、账户模型PasswordlessUserAccount的全部字段语义以及如何在 CAS Overlay 中以源码级方式编写并注册自定义存储让无密码登录直接对接你自有目录中的用户数据。自定义用户账户存储核心思路在 CAS 的 Passwordless 认证流程中当用户提交用户名后CAS 需要一个账户查找环节来决定该用户是否可以发起无密码认证以及应当向哪个联系方式邮箱/手机号发送一次性令牌。这一查找行为被抽象为PasswordlessUserAccountStore接口。官方文档 Passwordless-Authentication-Storage-Custom.md 明确指出你可以定义自己的用户账户存储只需实现PasswordlessUserAccountStore接口并以如下 Bean 定义将其注册到 CAS 运行时Bean public PasswordlessUserAccountStore passwordlessUserAccountStore() { ... }这里有两个关键点需要留意Bean 名称必须是passwordlessUserAccountStore。该名称正是接口中声明的常量BEAN_NAME见 PasswordlessUserAccountStore.javaCAS 的自动配置在装配默认存储时使用了ConditionalOnMissingBean(name PasswordlessUserAccountStore.BEAN_NAME)进行守卫见 CasPasswordlessAuthenticationAutoConfiguration.java。只要你的自定义 Bean 以同名注册CAS 就会跳过内部默认组装逻辑直接使用你的实现。注册位置自定义配置类需要能被 CAS 的AutoConfiguration机制扫描到。具体注册方法参见 Configuration-Management-Extensions.md将配置类全限定名写入src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件即可。接口定义与契约PasswordlessUserAccountStore位于support/cas-server-support-passwordless-api模块是一个标注了FunctionalInterface的接口源码见 PasswordlessUserAccountStore.javaFunctionalInterface public interface PasswordlessUserAccountStore { String BEAN_NAME passwordlessUserAccountStore; Optional? extends PasswordlessUserAccount findUser(PasswordlessAuthenticationRequest request) throws Throwable; default void reload() { } }接口契约包含两部分findUser(PasswordlessAuthenticationRequest request)唯一必须实现的方法。入参是封装了用户名的PasswordlessAuthenticationRequest返回Optional? extends PasswordlessUserAccount。返回Optional.empty()表示未找到该用户CAS 将拒绝发起无密码认证返回账户对象则表示命中后续流程将据此发送令牌。reload()默认空实现用于支持账户数据的运行时刷新。例如基于 JSON 文件的存储实现会通过它重读文件内容见下文。如果你的自定义存储有缓存或外部数据源变更场景建议重写该方法。请求对象PasswordlessAuthenticationRequestfindUser的入参类型为 PasswordlessAuthenticationRequest.java自 7.0.0 版本引入字段如下字段类型说明usernameString用户在登录页面提交的用户名必填providedUsernameString额外提供的用户名信息可为空propertiesMapString, String附加请求属性集合可用于传递上下文信息账户模型PasswordlessUserAccount返回的账户对象类型为 PasswordlessUserAccount.java其字段决定了无密码认证的后续行为字段类型默认值语义usernameString-用户名emailString-邮箱令牌将发送至此需与phone至少提供一个phoneJSON 字段名phoneNumberString-手机号令牌发送的备选渠道nameString-显示名称attributesMapString, ListObject空LinkedHashMap用户属性将并入最终认证主体PrincipalmultifactorAuthenticationEligibleTriStateBooleanUNDEFINED是否允许/要求多因素认证三态布尔可显式 true/false 或保持未定义delegatedAuthenticationEligibleTriStateBooleanUNDEFINED是否允许委托认证如通过外部 IdP 登录allowedDelegatedClientsListString空列表允许使用的委托客户端白名单requestPasswordbooleanfalse是否要求用户额外输入密码allowSelectionMenubooleanfalse是否允许显示账户选择菜单sourceString-账户来源标识其中hasContactInformation()方法用于校验账户是否具备联系方式email或phone至少一个非空这是 CAS 判断能否发送令牌的依据。该模型使用 Jackson 序列化JsonTypeInfo(use JsonTypeInfo.Id.CLASS)保留类型信息因此从 REST 或 JSON 数据源反序列化时返回结构需要与该字段集合兼容。CAS 内置的账户存储实现在动手编写自定义实现之前先了解 CAS 自带的几种PasswordlessUserAccountStore实现它们既可以直接使用也可以作为自定义实现的参考模板。全部位于support/cas-server-support-passwordless-api/src/main/java/org/apereo/cas/impl/account/目录实现类数据来源触发配置SimplePasswordlessUserAccountStore配置文件中的键值对cas.authn.passwordless.accounts.simple.*JsonPasswordlessUserAccountStoreJSON 文件cas.authn.passwordless.accounts.json.locationGroovyPasswordlessUserAccountStoreGroovy 脚本cas.authn.passwordless.accounts.groovy.locationRestfulPasswordlessUserAccountStoreREST 接口cas.authn.passwordless.accounts.rest.url组合器ChainingPasswordlessAccountStore需要注意CAS 默认装配的passwordlessUserAccountStore并非上述某一个实现而是一个组合存储ChainingPasswordlessAccountStore.java自动配置会收集容器中所有PasswordlessUserAccountStore类型的 Bean含内置的 JSON/Groovy/REST/Simple 存储与用户自定义存储按AnnotationAwareOrderComparator排序后包装为链式查找。findUser依次询问每个子存储返回第一个命中结果见 CasPasswordlessAuthenticationAutoConfiguration.java。这意味着如果你自定义的存储 Bean使用了其他名称而非passwordlessUserAccountStore它会被自动纳入默认链式存储中作为补充数据源如果你自定义的 Bean使用标准名称passwordlessUserAccountStore则完全替换掉默认链式存储此时你需要自行处理多数据源逻辑。SimplePasswordlessUserAccountStore配置驱动的极简实现该实现内部维护MapString, PasswordlessUserAccount accountsfindUser时使用正则匹配以配置中的 key 作为正则表达式对请求用户名做RegexUtils.find(key, username)匹配命中即返回对应账户见 SimplePasswordlessUserAccountStore.java。由于 key 被当作正则处理你甚至可以用user.*之类的模式批量匹配用户。其对应的测试用例 SimplePasswordlessUserAccountStoreTests.java 展示了最简配置形态cas.authn.passwordless.accounts.simple.casuser1234567890 cas.authn.passwordless.tokens.crypto.enabledfalse配置值会被自动识别为邮箱或手机号EmailValidator判定为合法邮箱则设置email否则设置phone见 CasPasswordlessAuthenticationAutoConfiguration.java。测试中casuser查询返回账户、other查询返回空验证了查找与 miss 两条路径。JsonPasswordlessUserAccountStore文件热加载该实现继承SimplePasswordlessUserAccountStore从 JSON 文件读取账户 Map并通过FileWatcherService监控文件变化一旦文件被修改就触发reload()重新加载见 JsonPasswordlessUserAccountStore.java。JSON 文件结构与账户模型对应例如{ casuser: { username: casuser, email: casuserexample.org, phoneNumber: 1234567890, name: CAS User, attributes: { memberOf: [staff] }, requestPassword: false, allowSelectionMenu: false } }GroovyPasswordlessUserAccountStore脚本驱动以 Groovy 脚本作为查找逻辑脚本入参为[request, logger]两个对象返回PasswordlessUserAccount或空见 GroovyPasswordlessUserAccountStore.java。脚本位置通过cas.authn.passwordless.accounts.groovy.location指定适合快速实现复杂查找规则而无需重新编译 Java 代码。RestfulPasswordlessUserAccountStoreREST 数据源将查找行为委托给远程 REST 接口CAS 以配置的 HTTP 方法请求url / username附带username请求参数与自定义 headers响应体按PasswordlessUserAccount.class反序列化支持 HJSON 解析返回2xx且有实体时即视为命中见 RestfulPasswordlessUserAccountStore.java。相关配置包括cas.authn.passwordless.accounts.rest.urlhttps://idm.example.org/api/passwordless/account cas.authn.passwordless.accounts.rest.methodGET cas.authn.passwordless.accounts.rest.basic-auth-usernameuser cas.authn.passwordless.accounts.rest.basic-auth-passwordsecret cas.authn.passwordless.accounts.rest.headers... cas.authn.passwordless.accounts.rest.maximum-retry-attempts3编写并注册自定义存储完整实战下面以对接企业自有用户目录为场景演示完整的自定义实现步骤。假设你的用户目录存储在一个内存 Map 或数据库中需要根据用户名返回PasswordlessUserAccount。第一步实现接口在 CAS Overlay 中新建配置类与存储实现package org.example.cas.config; import org.apereo.cas.api.PasswordlessAuthenticationRequest; import org.apereo.cas.api.PasswordlessUserAccount; import org.apereo.cas.api.PasswordlessUserAccountStore; import org.apereo.cas.authentication.principal.PrincipalFactory; import java.util.Optional; public class MyDirectoryPasswordlessUserAccountStore implements PasswordlessUserAccountStore { private final UserDirectoryService userDirectoryService; public MyDirectoryPasswordlessUserAccountStore(final UserDirectoryService userDirectoryService) { this.userDirectoryService userDirectoryService; } Override public Optional? extends PasswordlessUserAccount findUser( final PasswordlessAuthenticationRequest request) throws Throwable { final String username request.getUsername(); final UserRecord record userDirectoryService.findByUsername(username); if (record null) { return Optional.empty(); } return Optional.of(PasswordlessUserAccount.builder() .username(record.getUsername()) .email(record.getEmail()) .phone(record.getPhoneNumber()) .name(record.getDisplayName()) .attributes(Map.of(memberOf, List.of(record.getGroups()))) .requestPassword(false) .build()); } Override public void reload() { userDirectoryService.refreshCache(); } }第二步声明 Bean 并注册配置类参照官方文档给出的 Bean 定义并在配置类上补充AutoConfiguration与EnableConfigurationPropertiespackage org.example.cas.config; import org.apereo.cas.api.PasswordlessUserAccountStore; import org.apereo.cas.configuration.CasConfigurationProperties; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ScopedProxyMode; AutoConfiguration EnableConfigurationProperties(CasConfigurationProperties.class) public class CustomPasswordlessAccountStoreConfiguration { RefreshScope(proxyMode ScopedProxyMode.DEFAULT) Bean(name PasswordlessUserAccountStore.BEAN_NAME) public PasswordlessUserAccountStore passwordlessUserAccountStore( Qualifier(userDirectoryService) final UserDirectoryService userDirectoryService) { return new MyDirectoryPasswordlessUserAccountStore(userDirectoryService); } }要点说明Bean(name PasswordlessUserAccountStore.BEAN_NAME)显式使用标准 Bean 名称从而触发ConditionalOnMissingBean(name passwordlessUserAccountStore)条件使你的实现完全替换默认链式存储。RefreshScope(proxyMode ScopedProxyMode.DEFAULT)与 CAS 内部 Bean 定义保持一致外部配置变更触发上下文刷新时 Bean 可被重建CAS 官方文档 Configuration-Management-Extensions.md 亦推荐此写法。若你希望自定义存储作为补充数据源参与默认链式查找则去掉name属性改用如myPasswordlessUserAccountStore的自定义名称并可通过Order(...)控制查找顺序。第三步注册到 AutoConfiguration.imports创建或编辑src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件加入配置类全限定名org.example.cas.config.CustomPasswordlessAccountStoreConfiguration重启 CAS 后passwordlessUserAccountStore即为你自定义的实现。你可以通过 CAS 暴露的账户查询端点验证效果GET /cas/actuator/passwordless/account?usernamecasuser端点实现见 PasswordlessAuthenticationEndpoint.java。命中时返回账户 JSON200未命中返回 404同时端点会用默认PrincipalResolver解析用户并尝试将解析出的属性合并进账户attributes方便你观察最终账户数据。进阶账户定制器PasswordlessUserAccountCustomizer除存储实现外CAS 还提供了PasswordlessUserAccountCustomizer扩展点用于在存储查找完成后对账户做二次加工见 PasswordlessUserAccountCustomizer.java。它是一个Ordered接口customize(Optional? extends PasswordlessUserAccount)返回处理后的账户默认getOrder()为Ordered.HIGHEST_PRECEDENCE。SimplePasswordlessUserAccountStore的findUser在命中账户后会对所有非代理的 customizer 依次调用见 SimplePasswordlessUserAccountStore.java。CAS 内置的GroovyPasswordlessUserAccountCustomizer源码允许通过cas.authn.passwordless.core.passwordless-account-customizer-script.location指定 Groovy 脚本来动态修改账户属性脚本入参为[account, applicationContext, logger]。如果你的自定义存储想复用 customizer 机制可参考内置实现的做法在构造器中注入ListPasswordlessUserAccountCustomizer在findUser命中后遍历调用。存储查找链路与认证衔接为了完整理解自定义存储在整个无密码认证中的位置梳理关键调用链如下用户在登录页输入用户名CAS 触发无密码认证流程PasswordlessUserAccountStore.findUser(request)被调用可能经由ChainingPasswordlessAccountStore链式分发到你的自定义存储命中账户后CAS 依据账户的email/phone发送一次性令牌令牌由PasswordlessTokenRepository管理默认内存实现可配置 REST 后端见 CasPasswordlessAuthenticationAutoConfiguration.java用户提交令牌PasswordlessTokenAuthenticationHandler校验通过后完成认证账户attributes并入最终 Principal。从源码结构可以推断passwordlessUserAccountStoreBean 同时被认证处理器、端点等组件通过Qualifier(PasswordlessUserAccountStore.BEAN_NAME)引用因此只要标准 Bean 存在且行为正确整个认证链无需其他改动。小结自定义 Passwordless 用户账户存储是 CAS 无密码认证落地自有用户体系的标准做法核心就三步实现PasswordlessUserAccountStore接口、以标准 Bean 名称注册、通过AutoConfiguration.imports让 CAS 发现配置类。本文涉及的接口与实现均可在仓库中直接研读接口契约见 PasswordlessUserAccountStore.java账户模型见 PasswordlessUserAccount.java自动装配逻辑见 CasPasswordlessAuthenticationAutoConfiguration.java内置实现与测试见support/cas-server-support-passwordless-api/src/main/java/org/apereo/cas/impl/account/目录及 SimplePasswordlessUserAccountStoreTests.java。官方扩展机制的整体说明可参考 Configuration-Management-Extensions.md。赞分享后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载相关推荐Apereo CAS 无密码认证账户存储Passwordless Account Stores完全指南Apereo CAS 无密码认证账户存储Passwordless Account Stores完全指南 导读 本文以 Apereo CAS 官方文档 Pas后端认证鉴权单点登录Apereo CAS LDAP 密码无感认证账户存储Passwordless Authentication Storage实战指南Apereo CAS LDAP 密码无感认证账户存储Passwordless Authentication Storage实战指南 导读 本文讲解 Aper后端认证鉴权单点登录Apereo CAS Surrogate 认证之 JSON 账户存储配置实战指南Apereo CAS Surrogate 认证之 JSON 账户存储配置实战指南 Surrogate 认证又称模拟/代管认证即“Web 版 sudo”允许后端认证鉴权单点登录上一篇motionEye 性能调优技巧提升视频流处理效率的终极指南下一篇终极指南如何在Termux上快速安装和修复Metasploit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

【运维监控】Prometheus+grafana监控tomcat运行情况
【运维监控】Prometheus+grafana监控tomcat运行情况

运维监控系列文章入口:【运维监控】系列文章汇总索引 最近在研究 AI BI(智能数据分析) 的落地实践。 敬请期待后续专题实战系列:《从零手把手教你搭建 AI 驱动的 BI 系统》,将覆盖 Text2SQL、多轮对话、语义层、权限… · 2026/9/26 2:03:48

Skia 正确性测试实战:构建、运行与解读 DM 测试工具
Skia 正确性测试实战:构建、运行与解读 DM 测试工具

图形学图像处理 【免费下载链接】skia Skia is a complete 2D graphic library for drawing Text, Geometries, and Images. 项目地址: https://gitcode.com/gh_mirrors/skia1/skia 点击查看 免费下载 Skia 的正确性测试(Correctness Testing&#xff0… · 2026/9/26 2:03:42

51c大模型~合集140:EfficientVLA免训练推理加速实战,TaoToken统一Key接入配置指南
51c大模型~合集140:EfficientVLA免训练推理加速实战,TaoToken统一Key接入配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:03:42

LangGraph工作流编排实操:状态设计、人工介入与生产稳定性
LangGraph工作流编排实操:状态设计、人工介入与生产稳定性

写这个系列到第7篇,我明显感觉关注点变了:从"怎么写一个节点"变成了"整个工作流怎么组织才不会崩"。用LangGraph做AI工作流编排,玩到后面拼的根本不是提示词,而是状态管理、流程控制、人工介入和生产稳定性这… · 2026/9/26 2:37:26

Python轻量级农作物病虫害识别模型实战
Python轻量级农作物病虫害识别模型实战

简介:本资源是一套完整的Python毕业设计项目,面向计算机、农业信息化及相关专业本科生,解决农作物病虫害图像智能识别与分类的实际问题。项目基于深度学习技术构建端到端识别系统,涵盖数据采集规范、图像预处理流程、CNN模型搭建&… · 2026/9/26 2:37:26

用LangFlow搭建流量包推荐智能客服:RAG与对话记忆实战
用LangFlow搭建流量包推荐智能客服:RAG与对话记忆实战

简介:基于LangFlow框架的零代码大模型应用开发平台项目包,面向希望快速搭建智能客服与RAG应用的开发者、产品经理及运维人员。项目以“流量包推荐智能客服”为实战场景,完整演示对话记忆、检索增强生成(RAG)和多种模型… · 2026/9/26 2:37:20

游戏加加监控配置与帧数显示排查全攻略:从原理到实战
游戏加加监控配置与帧数显示排查全攻略:从原理到实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:37:20

基于迁移学习的昆虫识别系统实战:ResNet50+PyTorch+Flask部署
基于迁移学习的昆虫识别系统实战:ResNet50+PyTorch+Flask部署

简介:基于Python开发的昆虫识别系统,面向毕业设计、课程设计及实际项目开发,提供高精度识别能力与完整工程源码。系统采用模型迭代方式持续优化,最新版已支持2037个昆虫分类单元,Top1/Top5准确率分别达0.922/0.981&… · 2026/9/26 2:37:20

深入解析 zap 官方 FAQ:Go 高性能结构化日志库的设计取舍、采样机制与实战问答(基于 confd 仓库源码验证)
深入解析 zap 官方 FAQ:Go 高性能结构化日志库的设计取舍、采样机制与实战问答(基于 confd 仓库源码验证)

后端配置中心运维 【免费下载链接】confd Manage local application configuration files using templates and data from etcd or consul 项目地址: https://gitcode.com/gh_mirrors/co/confd 点击查看 免费下载 导读 go.uber.org/zap(以下简称 zap&a… · 2026/9/26 2:37:20

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码