配置与源码实现解析)
后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载本文围绕 Apereo CAS 的 SAML2 Identity ProviderIdP能力讲解如何通过 Metadata Query ProtocolMDQ元数据查询协议从远程元数据服务器动态拉取 SP 的元数据。内容包括注册服务的 JSON 配置方法、cas.authn.saml-idp.metadata.mdq配置项说明以及结合 CAS 源码对占位符替换、ETag 缓存、备份文件兜底等底层机制的完整剖析。什么是 MDQCAS 为什么需要它在传统的 SAML IdP 集成中SPService Provider的元数据通常通过静态文件、固定 URL 或人工维护的方式提供给 IdP。当 SP 的断言签名密钥、SSO 端点等配置发生变更时IdP 端往往需要同步更新文件并重启或等待缓存过期。CAS 支持 Metadata Query ProtocolMDQ来解决这一问题。MDQ 是一种 REST 风格的 API允许客户端按 entityID 动态查询实体元数据。配置后CAS 的 SAML 服务会在运行时向 MDQ 服务器发起查询请求实时获取最新的 SP 元数据从而避免人工维护静态元数据文件。原始文档见 Configuring-SAML2-DynamicMetadata-MDQ.md。配置一个使用 MDQ 的 SAML 注册服务要让某个 CAS SAML 服务通过 MDQ 服务器获取元数据核心做法是将注册服务定义中的metadataLocation指向 MDQ 查询服务器实例。文档给出的完整配置示例如下{ class : org.apereo.cas.services.SamlRegisteredService, serviceId : the-entity-id-of-the-sp, name : SAMLService, id : 10000003, evaluationOrder : 10, metadataLocation : https://mdq.server.org/entities/{0} }配置要点serviceIdSP 的 entityID是 CAS 匹配请求时识别该服务的主要依据metadataLocationMDQ 查询服务器的地址。其中的{0}是一个 entityID 占位符由 CAS 在运行时动态处理并替换为实际要查询的实体 ID经 URL 编码后填入该属性支持逗号分隔的多个位置CAS 会依次处理多个元数据地址。源码如何识别一个 MDQ 位置从源码结构看CAS 判断某个metadataLocation是否为 MDQ 配置的依据非常明确——位置必须以/entities/{0}结尾。这一逻辑实现在 SamlUtils.javapublic static boolean isDynamicMetadataQueryConfigured(final String metadataLocation) { return StringUtils.isNotBlank(metadataLocation) metadataLocation.trim().endsWith(/entities/{0}); }MDQ 解析器通过该方法决定自己是否“认领”这个服务而通用的 URL 元数据解析器则会主动排除 MDQ 形式的位置见 UrlResourceMetadataResolver.java二者互不干扰// MetadataQueryProtocolMetadataResolver.supports() return locations.stream().anyMatch(SamlUtils::isDynamicMetadataQueryConfigured);运行时流程占位符替换、ETag 与备份兜底MDQ 的核心实现类是 MetadataQueryProtocolMetadataResolver.java它继承自UrlResourceMetadataResolver并覆盖了三个关键方法对应 MDQ 与普通 URL 拉取元数据的所有差异。1. 动态确定要查询的 entityID 与 URL在getMetadataLocationsForService中解析器优先从查询条件CriteriaSet中取出EntityIdCriterion携带的 entityID若不存在则回退到注册服务自身的serviceIdval entityId Optional.ofNullable(entityIdCriteria) .map(EntityIdCriterion::getEntityId) .orElseGet(service::getServiceId); if (StringUtils.isBlank(entityId)) { throw new SamlException(Unable to determine entity id to fetch metadata via MDQ for service.getName()); }随后每个候选位置中的{0}占位符都会被替换为 URL 编码后的 entityIDlocation.replace({0}, EncodingUtils.urlEncode(entityId))得到最终的 MDQ 查询 URL。这也解释了为什么文档强调{0}是“运行时动态处理并替换”的——同一个metadataLocation配置可以服务不同的实体。2. 请求构造Basic 认证、Content-Type 与 If-None-MatchfetchMetadata方法构造实际 HTTP 请求请求头与参数全部来自 MDQ 专用配置即cas.authn.saml-idp.metadata.mdq属性组val metadata samlIdPProperties.getMetadata().getMdq(); headers.put(HttpHeaders.CONTENT_TYPE, metadata.getSupportedContentType()); headers.put(HttpHeaders.ACCEPT, */*); ... val exec HttpExecutionRequest.builder() .basicAuthPassword(metadata.getBasicAuthnPassword()) .basicAuthUsername(metadata.getBasicAuthnUsername()) .method(HttpMethod.GET) .url(metadataLocation) .headers(headers) .proxyUrl(service.getMetadataProxyLocation()) .build();可以观察到几个实战相关细节Basic 认证basicAuthnUsername/basicAuthnPassword用于对接需要认证的 MDQ 服务器内容类型请求携带Content-Type头其值由supportedContentType配置控制ETag 条件请求若本地存在上一轮拉取产生的备份文件CAS 会读取文件属性中缓存的 ETag 并以If-None-Match头发出条件请求headers.put(If-None-Match, etag)支持 MDQ 服务器返回 304 以节省带宽。MDQ 解析器重写了shouldHttpResponseStatusBeProcessed直接返回true意味着 304 等非 2xx 状态也会被显式处理而不是按失败丢弃代理支持沿用注册服务的metadataProxyLocation。3. 响应处理写备份文件、失败回退getMetadataResolverFromResponse定义了成功与失败两条路径成功2xx将响应体写入本地备份文件把响应头中的ETag保存为文件自定义属性user:ETag再用InMemoryResourceMetadataResolver从备份文件构建内存解析器供后续使用失败非 2xx如果本地备份文件存在则直接回退使用该备份文件构建解析器保证 SSO 不因 MDQ 服务器瞬时故障而中断若备份也不存在则抛出SamlException(Unable to get entity from MDQ server and a backup file does not exist.)5xx 或无响应在fetchMetadata中直接抛出UnauthorizedServiceException日志记录Unable to fetch metadata from [...]由上层UrlResourceMetadataResolver捕获并转换为SamlException。另外MDQ 场景下备份文件的命名与普通 URL 拉取不同文件名前缀取的是service.getServiceId()的 SHA 摘要见 UrlResourceMetadataResolver.java 中的getBackupMetadataFilenamePrefix即同一个 SP 无论查询条件如何变化备份都落在同一个稳定路径上这正是 ETag 条件请求与故障回退能正常工作的前提。cas.authn.saml-idp.metadata.mdq配置项说明文档末尾引用的cas.authn.saml-idp.metadata.mdq属性组对应源码类 MDQSamlMetadataProperties.java其字段与用途如下配置项类型默认值说明cas.authn.saml-idp.metadata.mdq.basic-authn-usernameString无连接 MDQ 服务器时使用的 Basic 认证用户名cas.authn.saml-idp.metadata.mdq.basic-authn-passwordString无连接 MDQ 服务器时使用的 Basic 认证密码cas.authn.saml-idp.metadata.mdq.supported-content-typeStringtext/xml向 MDQ 服务器发起请求时携带的Content-Type值源码注释标明默认支持text/xml这些属性挂在 SamlIdPMetadataProperties.java 的mdq字段下与core、http、fileSystem等其它元数据属性组并列因此 MDQ 配置不影响其它元数据解析方式的行为。MDQ 解析器在整体解析计划中的位置MDQ 解析器不是孤立存在的它是 CAS SAML 注册服务元数据解析链中的一环。在 SamlIdPMetadataConfiguration.java 中CAS 注册了六个默认解析器 Bean并通过Order指定优先级解析器 Bean顺序适用场景metadataQueryProtocolMetadataResolverHIGHEST_PRECEDENCE最高以/entities/{0}结尾的 MDQ 位置jsonResourceMetadataResolver1metadataLocation为 JSONfileSystemResourceMetadataResolver2文件系统路径urlResourceMetadataResolver3普通 HTTP(S) URLclasspathResourceMetadataResolver4classpath 资源groovyResourceMetadataResolver5Groovy 脚本这些解析器由defaultSamlRegisteredServiceMetadataResolutionPlanConfigurer依次注册进DefaultSamlRegisteredServiceMetadataResolutionPlan再由带缓存的SamlRegisteredServiceDefaultCachingMetadataResolver统一调度缓存加载逻辑见chainingMetadataResolverCacheLoader。因此 MDQ 拉取到的元数据同样享受 CAS 的缓存策略不会每次 SSO 都发起远程查询SamlRegisteredServiceCacheKey在构造缓存键时也专门对 MDQ 配置做了区分处理见 SamlRegisteredServiceCacheKey.java。需要注意的是整套配置仅在启用了 SAML IdP 功能模块CasFeatureModule.FeatureCatalog.SAMLIdentityProvider时生效且SamlIdPMetadataConfiguration类上带有ConditionalOnFeatureEnabled条件注解对应模块为cas-server-support-saml-idp及元数据解析扩展模块cas-server-support-saml-idp-metadata。测试验证仓库中 MetadataQueryProtocolMetadataResolverTests.java 对该解析器做了单元测试验证了supports判定、占位符替换后的查询地址构造以及请求头组装等行为可作为对接自有 MDQ 服务器时的预期行为参照。小结CAS 通过把注册服务的metadataLocation配置为以/entities/{0}结尾的 MDQ 地址来启用动态元数据查询{0}在运行时被替换为 URL 编码的 entityID支持逗号分隔多个地址请求层面支持 Basic 认证basic-authn-username/basic-authn-password、可配置Content-Type默认text/xml并基于本地备份文件自动携带If-None-MatchETag 头拉取成功后元数据落盘为备份文件查询失败时可回退到备份文件彻底失败才报错兼顾了实时性与可用性MDQ 解析器在解析计划中优先级最高但只“认领” MDQ 形式的位置其余位置仍由 JSON/文件系统/URL 等解析器按序处理整体接入对现有 SAML IdP 部署无侵入。赞分享后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载相关推荐Apereo CAS 配置 SAML2 UnsolicitedIdP-InitiatedSSO 详解Apereo CAS 配置 SAML2 UnsolicitedIdP InitiatedSSO 详解 Apereo CAS 作为 SAML2 身份提供方I后端认证鉴权单点登录Apereo CAS 基于 Amazon S3 的 SAML2 动态元数据管理SP 元数据解析与 IdP 元数据托管实战Apereo CAS 基于 Amazon S3 的 SAML2 动态元数据管理SP 元数据解析与 IdP 元数据托管实战 Apereo CAS 作为 SAML后端认证鉴权单点登录Apereo CAS SAML2 Git 元数据管理SP 与 IdP 元数据的版本控制实战Apereo CAS SAML2 Git 元数据管理SP 与 IdP 元数据的版本控制实战 本篇技术指南聚焦 Apereo CAS 中 SAML2 元数据的后端认证鉴权单点登录上一篇408数据结构代码题终极攻略5大核心算法模板快速掌握下一篇asc-devkit矩阵乘法最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考