☰
Apereo CAS 密码管理之 JSON 存储:配置文件格式、参数详解与源码实现
2026/10/15 2:45:21 网站建设 项目流程
  • 后端
  • 认证鉴权
  • 单点登录

【免费下载链接】cas

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

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

JSON 是 Apereo CAS 密码管理(Password Management)功能支持的最简单账户存储后端:账户与密码被存放在一个静态的 JSON 资源文件中,通过cas.authn.pm.json.location一个配置项即可接入。本文以 Password-Management-JSON.md 为骨架,结合仓库中cas-server-support-pm-core与cas-server-support-pm模块的源码与测试,完整讲解 JSON 文件格式、开启方式、可用配置参数、底层工作机理及其适用边界,让读者既能快速上手,也能理解其内部实现。

JSON 后端的定位与适用场景

CAS 官方文档对 JSON 存储给出了明确的定位:账户与密码保存在一个静态的、精简的 JSON 资源中,其位置通过 CAS 配置告知系统。这一选项最适合开发、测试与演示环境,不适合生产环境。

从仓库实现看,JSON 后端对应的服务类为JsonResourcePasswordManagementService,位于 support/cas-server-support-pm-core/src/main/java/org/apereo/cas/pm/impl/JsonResourcePasswordManagementService.java,它在 CAS 的密码管理存储清单(JSON、Groovy、LDAP、JDBC、REST、Custom,见 Password-Management.md 的 Storage 小节)中属于最简单的实现:不需要数据库、目录服务或外部 HTTP 服务,只要一个可读(必要时可写)的 JSON 文件即可支撑忘记密码、修改密码、密保问题等基础流程。

开启 JSON 密码管理:依赖与配置

密码管理整体功能需要cas-server-support-pm-webflow模块(在 WAR overlay 中加入该依赖即可启用相关 Webflow)。在此基础上,JSON 后端仅需在application.properties(或 YAML)中配置两个属性:

# 开启密码管理核心功能(必填) cas.authn.pm.core.enabled=true # 指定 JSON 账户文件的位置(必填) cas.authn.pm.json.location=file:/etc/cas/config/pm-accounts.json
  • cas.authn.pm.core.enabled在配置模型 PasswordManagementCoreProperties.java 中被标注为@RequiredProperty,即密码管理功能的总开关。
  • cas.authn.pm.json.location对应配置模型 JsonPasswordManagementProperties.java,它继承自 SpringResourceProperties.java,location同样为@RequiredProperty。该属性支持 Spring 资源定位语法:既可以是file:/绝对路径,也可以是classpath:xxx.json或https://...等 URL。

值得注意的是,CAS 采用按需装配策略:只有在环境中检测到cas.authn.pm.json.location属性存在时,才会创建JsonResourcePasswordManagementService这个 Bean。这一判断逻辑位于 CasPasswordManagementAutoConfiguration.java:

return () -> BeanSupplier.of(PasswordManagementService.class) .when(BeanCondition.on("cas.authn.pm.json.location").exists().given(applicationContext.getEnvironment())) .supply(() -> new JsonResourcePasswordManagementService(passwordManagementCipherExecutor, casProperties, location, passwordHistoryService)) .otherwiseProxy() .get();

即:配置了cas.authn.pm.json.location,JSON 后端即被激活;未配置则返回代理占位,不会影响其他存储后端的装配。该服务还会注入passwordManagementCipherExecutor(用于重置令牌的加解密)和passwordHistoryService(用于密码历史校验)。

相关的可选核心参数

围绕密码管理核心功能,PasswordManagementCoreProperties.java 还提供了以下可选参数:

配置项默认值说明
cas.authn.pm.core.enabled无(必填)是否启用密码管理功能
cas.authn.pm.core.auto-loginfalse密码修改成功后是否自动完成登录
cas.authn.pm.core.password-policy-pattern^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,10}新密码必须满足的正则策略:默认要求 8~10 位、至少 1 个大写、1 个小写、1 个数字和 1 个特殊字符
cas.authn.pm.core.password-policy-character-setabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789![]{}()%&*$#^<>~@\|CAS 生成/建议新密码时使用的字符集
cas.authn.pm.core.password-policy-password-length10CAS 建议密码的默认长度

这些参数与存储后端无关,JSON 后端同样适用;例如仓库测试用例 JsonResourcePasswordManagementServiceTests.java 中就用cas.authn.pm.core.password-policy-pattern=^Test1.+验证了密码策略校验行为。

JSON 账户文件格式详解

官方文档给出的账户文件结构如下(顶层是一个以用户名为键的映射):

{ "casuser" : { "email" : "casuser@example.org", "password" : "p@ssw0rd", "phone" : "1234567890", "status": "OK", "securityQuestions" : { "question1" : "answer1", "question2" : "answer2" } } }

每个账户对象对应源码中JsonBackedAccount内部类(JsonResourcePasswordManagementService.java)的字段,两者一一对应:

JSON 字段类型含义与用途
emailString账户邮箱,用于"忘记用户名"(findUsername)与找回/重置流程中的邮件投递
passwordString明文密码。源码中密码以明文 String 直接存放于 JSON,这是其不适合生产环境的重要原因
phoneString手机号,用于短信通知类流程(findPhone)
statusString账户状态。源码中unlockAccount会检测locked状态并将其改写为OK,用于账户解锁场景
securityQuestionsMap<String, String>密保问题与答案的键值对,用于重置密码时的身份校验与更新

仓库测试资源 support/cas-server-support-pm/src/test/resources/jsonResourcePassword.json 提供了与此格式完全一致的实例,可作为编写自定义账户文件的直接模板。

一个值得注意的细节:HJSON 解析

JsonResourcePasswordManagementService在读取文件时并非直接使用标准 JSON 解析,而是先经JsonValue.readHjson(reader)处理后再交给 Jackson 反序列化(见 JsonResourcePasswordManagementService.java):

val personList = new TypeReference<Map<String, JsonBackedAccount>>() {}; jsonBackedAccounts = MAPPER.readValue(JsonValue.readHjson(reader).toString(), personList);

这意味着账户文件实际上按HJSON(Human JSON)语法解析,允许在文件中书写#注释、省略多余的引号或容忍尾随逗号,便于人工维护。

从源码看 JSON 后端的能力边界

JsonResourcePasswordManagementService继承自 BasePasswordManagementService.java,后者实现了令牌创建/解析与带审计、密码历史检查的通用change流程,前者则逐一实现与 JSON 文件交互的具体操作:

  • 修改密码:changeInternal先校验新密码非空、与确认密码一致、且用户存在于文件中,随后更新内存中的账户并调用writeAccountToJsonResource()写回文件。
  • 查找邮箱:findEmails按用户名返回邮箱集合(用于发送重置/找回邮件)。
  • 查找手机号:findPhone按用户名返回手机号。
  • 查找用户名:findUsername按邮箱反向定位用户名,支撑"忘记用户名"功能。
  • 密保问题:getSecurityQuestions返回账户的密保问题映射;updateSecurityQuestions支持用户自助更新密保问答并写回文件。
  • 账户解锁:unlockAccount将status为locked的账户改写为OK并持久化。

这些能力在 JsonResourcePasswordManagementServiceTests.java 中均有对应测试用例:例如verifyUserEmailCanBeFound验证按用户名找回邮箱、verifyUserCanBeFound验证按邮箱找回用户名、verifyUserPhoneCanBeFound验证手机号查询、verifyUnlock验证账户解锁、verifyUserQuestionsCanBeFound与verifySecurityQuestions验证密保问题的读取与更新、verifyUserPasswordChange/verifyUserPasswordChangeFail验证密码修改的成功与失败分支、verifyPasswordValidationService验证密码策略正则的生效,以及verifyToken验证重置令牌的创建与解析。

密码修改的写回机制:classpath 资源只读

writeAccountToJsonResource()的实现值得注意(JsonResourcePasswordManagementService.java):

MAPPER.writerWithDefaultPrettyPrinter().writeValue(jsonResource.getFile(), jsonBackedAccounts); readAccountsFromJsonResource();

它调用jsonResource.getFile()把整个账户映射以美化格式写回原文件。这意味着:

  • 读取(登录校验前的邮箱/密保查询等)可以走classpath:等只读资源;
  • 写回(修改密码、更新密保、解锁账户)必须指向文件系统上真实可写的路径,否则getFile()会失败。生产实践中应使用file:/...绝对路径并确保 CAS 进程对该文件有写权限;
  • 文件整体读写、无锁无事务,并发修改场景下可能互相覆盖,这也是官方将其限定为开发/测试/演示用途的原因之一。

通用流程的支撑:密码历史与审计

上层change方法(BasePasswordManagementService.java)带有@Audit(action = AuditableActions.CHANGE_PASSWORD, ...)审计注解,并在写回前先通过passwordHistoryService.exists(bean)检查新密码是否命中密码历史策略、写回后调用passwordHistoryService.store(bean)记录历史。也就是说,即使存储后端是 JSON,密码历史(Password-Management-History.md)与审计日志依然生效,只是密码历史本身需要另行配置存储位置。

密码重置令牌:JSON 后端同样支持

密码重置功能与存储后端解耦。BasePasswordManagementService中createToken/parseToken负责生成与校验重置令牌:

  • 令牌本质是包含jti、issuer(CAS 服务前缀)、audience、subject(用户名)、签发时间与过期时间的 JWT 风格声明集合,再经cipherExecutor编码(BasePasswordManagementService.java)。
  • 解析时校验签发者、受众、subject 是否匹配,并可依据cas.authn.pm.reset.include-server-ip-address、cas.authn.pm.reset.include-client-ip-address校验来源 IP,最后校验过期时间(BasePasswordManagementService.java)。
  • 令牌有效期由cas.authn.pm.reset.expiration控制,配置模型 ResetPasswordManagementProperties.java 中默认值为PT1M。

因此,即使用户账户存放在 JSON 文件中,忘记密码后通过邮件/短信发送重置链接、点击链接完成改密的完整闭环依然可用。更完整的重置流程可参考 Password-Management-Reset.md 与 Password-Management-ForgotUsername.md。

与其他存储后端的取舍

在 CAS 的密码管理存储选项中(Password-Management.md),JSON 是唯一"零依赖"的静态文件方案:相比 Password-Management-LDAP.md、Password-Management-JDBC.md 与 Password-Management-REST.md,它无需任何外部服务即可在数分钟内完成演示环境搭建;相比 Password-Management-Groovy.md 的脚本化实现,它无需编写脚本逻辑。但相应的代价是:明文密码、整文件读写、无并发控制,因此官方明确建议生产环境改用 LDAP/JDBC/REST 等后端,或用 Password-Management-Custom.md 对接自建账户管理应用。

小结:三分钟跑通 JSON 密码管理

  1. 在 WAR overlay 中加入cas-server-support-pm-webflow依赖;
  2. 编写pm-accounts.json,顶层以用户名为键,账户内含email、password、phone、status、securityQuestions字段;
  3. 配置cas.authn.pm.core.enabled=true与cas.authn.pm.json.location=file:/.../pm-accounts.json;
  4. 重启 CAS,即可体验忘记用户名、密保问答、重置密码与账户解锁等流程;源码与测试用例(JsonResourcePasswordManagementServiceTests.java)可作为理解每一步行为的最佳参考。
  • 后端
  • 认证鉴权
  • 单点登录

【免费下载链接】cas

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

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

相关推荐

上一篇:深度解析LibVLCSharp:跨平台高性能媒体播放架构揭秘
下一篇:5个步骤解决Balena Etcher Mac OS下载故障:开源工具资源获取完整指南

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询