ARTICLE DETAIL

资讯详情

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

2026 Java 单点登录选型指南:CAS、OAuth2、OIDC、SAML 四协议对照与落地路径

2026 Java 单点登录选型指南:CAS、OAuth2、OIDC、SAML 四协议对照与落地路径 2026 Java 单点登录选型指南CAS、OAuth2、OIDC、SAML 四协议对照与落地路径开篇先澄清一个被反复混淆的问题——SSO 到底在解决什么很多 Java 团队在做单点登录立项时第一个动作是去搜CAS 和 OAuth2 哪个好第二个动作是把某个开源认证中心跑起来第三个动作才在联调时发现登出不生效、Token 无法吊销、跨企业对接时对方只给一份 SAML 元数据。这三个问题都不是协议选错了而是立项阶段没有把三个不同的问题拆开。单点登录Single Sign-OnSSO解决的是**认证Authentication**问题用户在一处证明我是谁之后其余互信系统不再重复要求输入凭证。与它相邻但不同的还有两个问题统一授权Authorization认证之后这个用户能访问哪些资源、执行哪些操作。OAuth 2.0 的规范定义是开放授权框架核心产物 access_token 表达的是授权访问资源而不是已证明身份[1][4]单点登出Single LogoutSLO在一处登出后其余系统是否同步失效。它与 SSO 是一对对偶需求且实现成本常常高于登录本身。这三者的边界直接决定协议选型是否成立。最常见的误区是用 OAuth2 做 SSO——准确的表述应当是OAuth2 负责授权流程身份层由 OIDC 的 ID Token 或自建用户信息端点补足凭证载体为 JWT。研究资料中的多篇实战文章也把 OIDC 定位为认证 授权而把 OAuth2.0 单独定位为授权访问资源两者不是并列候选而是叠加关系[1][3]。在继续选型之前还要统一四个术语**认证中心/IdP身份提供方**签发凭证**业务系统/SP/RP服务提供方或依赖方**消费凭证**会话Session**是应用本地的状态**凭证Ticket/Token/Assertion**是跨系统传递的证明材料。SSO 的所有技术主线本质上都是在这四个对象之间安排不同的信任边界。一、四协议对照核心目的、凭证格式、适用场景、落地难度1.1 一张表看懂四协议 × 四维度下表是技术评审时可直接引用的对照口径。需要强调的是落地难度是经验判断而非客观指标实际难度取决于团队技术栈、是否已有 IdP、组织间协调成本三个变量不能机械照搬表格结论[1]。协议核心目的凭证格式适用场景落地难度典型生态CASApereo CAS 协议单点登录认证Service Ticket一次性、不透明、服务端校验Java 技术栈、存量系统、企业内异构老系统中等已有 CAS Server 时明显降低Apereo CAS Server、CAS Client、Spring Security 集成OAuth 2.0授权访问资源非认证协议access_tokenBearer 形式可为不透明字符串或 JWTAPI 授权、开放平台、第三方登录中等自建授权服务器成本高于接入托管 IdPSpring Authorization Server、Keycloak、各类云 IdPOIDC认证 授权在 OAuth2 之上叠加身份层ID TokenJWT认证专用 access_token前后端分离、新项目、跨域 SPA/移动端视生态而定Spring 生态下客户端接入较顺Spring Security OAuth2 Login、Keycloak、MaxKey 等SAML 2.0企业级认证断言XML 断言可签名、可加密跨企业集成、传统企业 IdP 对接较高XML 签名、证书交换、双向元数据配置Shibboleth、各类企业 IdP、Spring Security SAML对比研究资料中给出的表格[1]本文保留其四维度框架但做了两处修正一是 OIDC 一栏补充实际同时存在 access_token避免读者误以为只发 ID Token二是去掉了绝对化的难度定级改为条件化表述。1.2 三种凭证的实物化理解理解凭证格式的差异比背协议流程更有效。下面是三种凭证的结构示意仅表达形状不写具体值CAS Service Ticket: ST-1234-abcd.... # 不透明字符串一次性CAS Server 端记录并校验 JWTOIDC ID Token / OAuth2 access_token: header {alg:RS256,kid:key-2026-01} payload {iss:...,sub:...,aud:...,exp:...} signature RS256(header . payload) SAML Assertion: saml:Assertion ... Signature.../Signature ... /saml:Assertion由此可以推出三条工程判断不透明 Ticket 便于服务端即时吊销代价是每次校验都要回源认证中心JWT 自带签名可本地离线校验代价是默认无法主动失效需要黑名单或短有效期补偿SAML 断言携带签名与时间条件安全表达力最强但解析、签名验证、证书管理的实现成本最高。1.3 三个最容易被混淆的点其一OAuth2 与 OIDC 是叠加而非并列。OIDC 在 OAuth2 授权码流程之上增加 ID Token 与标准化的用户信息端点把授权补全为认证。因此严格说纯 OAuth2 流程不能直接宣称完成 SSO除非另行约定用 access_token 调用用户信息端点来推断身份——这在实践中可行但属于自建身份层[1][3]。其二CAS 协议不等于集中式会话。CAS 的会话状态保存在 CAS Server业务系统SP持有自己的本地会话。用户首次访问 SP 时被重定向到 CAS Server认证后 CAS 签发 Service TicketSP 拿 Ticket 回 CAS 验证通过后建立本地会话[2]。也就是说CAS 是一套票据协议而不是简单的共享 Session。其三SAML 的重来自组织边界而不只是 XML。XML 签名、证书交换、SP/IdP 元数据双向配置、证书轮换流程、跨组织故障责任划分每一项都需要双方运维配合。跨企业集成时真正的成本往往不在代码而在协调。二、三条技术主线Session 共享、CAS、OAuth2JWT协议是标准主线是 Java 生态中的落地形态。同样是OIDC用 Spring Security OAuth2 Login 接入现成 IdP与自建 Spring Authorization Server工作量相差一个量级。下面三条主线覆盖了绝大多数 Java 团队的现实选择[3][9]。2.1 主线一Session 共享同域共享 Cookie 集中式 Session 存储机制所有系统部署在同一主域下如a.example.com、b.example.comCookie 作用域设为.example.comSession 数据集中存储在 Redis各服务从同一存储读取会话[2]。Spring Session 提供了成熟的 Redis 集成。// 骨架示例具体 API 与配置项以实际依赖版本的官方文档为准ConfigurationEnableRedisHttpSession(maxInactiveIntervalInSeconds1800)publicclassSessionConfig{BeanpublicLettuceConnectionFactoryconnectionFactory(){// 生产环境建议配置哨兵或集群并为 Session 划分独立 Redis 实例/DBreturnnewLettuceConnectionFactory();}}改造成本最低几行配置即可让多个系统共享登录状态[3]。但边界同样最硬要求同主域或同顶级域跨域、跨企业无法覆盖要求技术栈可控非 Java 系统接入需自行实现 Redis Session 协议Cookie 属性Domain、Path、Secure、HttpOnly、SameSite一旦设置错误会直接表现为登录成功但第二个系统仍要求登录。主要工程点是登出与互踢。一个可参考的思路是在 Redis 记录当前端类型的最新凭证鉴权时比对是否一致[10]Key: login:{端类型}:{用户ID} 例如 login:APP:10086 Value: 当前有效凭证标识 TTL: 与凭证有效期保持一致新登录写入新值即可顶掉旧值实现同端互踢鉴权发现凭证与记录不一致时判定为被踢下线[10]。注意这只是设计思路实际 Key 命名、TTL、并发写入策略须按业务重设计不要照抄。2.2 主线二CASApereo CAS 协议流程用户访问 SP → SP 重定向到 CAS Server → 认证后签发 Service Ticket一次性临时票据→ SP 后端拿 Ticket 回 CAS 验证 → 建立本地会话[2][8]。经典实现中还存在三个关键对象用户全局会话、存放在 CAS 端 Cookie 的全局门票、一次性临时票据[8]。**单点登出SLO**是 CAS 的强项之一也是最容易被忽略的验收项。实践中常见做法是通过登出过滤器接收 CAS Server 的登出回调将 Service Ticket 与当前 Session 绑定实现统一失效[3]。跨企业或大规模场景还涉及 front-channel / back-channel 等不同登出方式具体机制应以 Apereo CAS 官方协议文档为准本文不臆造细节。适用面已有 CAS Server 的存量企业、Java 技术栈、多子域内网系统、异构老系统集成。有实测文章给出了 CAS Server 5.3.16 与 RuoYi-Vue 4.6.0 的接入复盘SSO 与 SLO 均可跑通[6]也有文章介绍了 CAS 服务端的搭建、证书导入与基础配置过程[7]。痛点集中在前后端分离改造传统 CAS 客户端依赖服务端 302 重定向而 SPA 期望 JSON 响应。常见改造是把未认证请求统一返回 401由前端决定跳转登录页[18]。另外客户端依赖坐标与版本线容易踩坑——有资料提示 Apereo CAS Client 4.x 为 Jakarta 兼容版Spring Boot 2.x 环境需使用旧坐标与 3.6.x 版本[3]。该说法属于转述落地前务必以 Apereo 官方发布信息核对坐标与版本。2.3 主线三OAuth2 JWT可叠加 OIDC组成授权服务器采用授权码模式 JWT 作为凭证载体 资源服务器验签 网关统一校验。这套组合无状态、天然跨域是前后端分离微服务的主流路径[3][9]。技术栈上有一个值得注意的迁移信号有资料称 Spring Security 5.7 之后官方推荐使用独立的 Spring Authorization Server 项目替代旧版spring-security-oauth2后者长期处于维护模式旧注解EnableOAuth2Sso、WebSecurityConfigurerAdapter逐渐进入历史方案语境[4][17]。该转述的具体版本线需以 Spring 官方迁移文档为准但它提示的方向是明确的新项目不应再围绕旧版spring-security-oauth2构建。授权服务器的客户端注册骨架大致如下API 名称以实际依赖版本编译验证为准[5]BeanpublicRegisteredClientRepositoryregisteredClientRepository(JdbcTemplatejdbcTemplate){RegisteredClientclientRegisteredClient.withId(UUID.randomUUID().toString()).clientId(sso-client).clientSecret(passwordEncoder().encode(secret))// 禁止使用 {noop} 明文写入生产.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).redirectUri(https://app.example.com/login/oauth2/code/sso-client).scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).build();returnnewInMemoryRegisteredClientRepository(client);}必须在立项阶段就定的工程要点双令牌与刷新access_token 短有效期分钟级refresh_token 长有效期并做轮换与复用检测吊销与黑名单JWT 默认无状态登出或封号时需引入 Redis 黑名单配合短有效期控制影响窗口[3]密钥管理建议 RS256 非对称签名资源方只持有公钥用kid支持密钥轮换私钥不进代码仓库、不入日志标准校验项iss、aud、exp、nbf校验缺一不可另需考虑适度的时钟偏移容忍。用一句话概括这条主线的工程分工某实战文章的总结是OAuth2 管流程 JWT 管凭证 Redis 管黑名单 RS256 管密钥[3]。这是经验总结而非规范表述但它准确指出了四类关注点的归属。2.4 三条主线横向对比主线会话/凭证形态登出能力跨域能力改造成本典型风险Session 共享服务端 Session 共享 Cookie易实现本地会话即全局限同主域低Cookie 作用域、Session 过期不一致、单点失效CASST 临时票据 各系统本地会话SLO 成熟需正确挂接登出过滤器支持跨子域中前后端分离下 401/重定向处理、客户端版本兼容OAuth2JWTaccess_tokenJWT refresh_token弱需黑名单/短有效期补偿天然跨域中高无法主动失效、密钥轮换、iss/aud 校验缺失三、三类典型场景的推荐路径3.1 场景一同域内网多系统场景约束所有系统在同一主域或内网团队可控追求快速上线无对外集成诉求。推荐路径首选Session 共享Spring Session Redis或顶级域共享 Cookie。改造成本极低几行配置即可上线[3][9]。若后续出现以下任一条件再升级到 CAS 或 OIDC出现多技术栈系统需要统一登录页与规范化 SLO系统数量增长到需要独立审计与授权粒度。该场景特有的坑Cookie 作用域与 SameSite。Domain必须是主域如.example.comSameSiteLax在跨子域跳转场景下通常可用但若存在跨站跳转回跳需要专门验证Secure与HttpOnly在内网 HTTP 环境与 HTTPS 环境行为不同务必在目标环境实测。负载均衡下的 Session 一致性。开启粘性会话ip_hash 或 cookie 路由与集中式 Session 存储二选一时建议直接用后者避免扩缩容后部分用户被强制登出。登出是否真正全链路失效。共享 Session 方案下登出看似简单但各系统的本地缓存、前端缓存、WebSocket 长连接往往没有同步清理需在验收用例中覆盖。互踢策略提前约定。同一账号多端登录是允许还是互斥直接决定 Redis Key 设计与用户体验[10]。3.2 场景二前后端分离 微服务场景约束前端独立部署且跨域、后端多服务、有 API 网关、要求无状态横向扩展。推荐路径OAuth2 授权码模式 OIDC JWT认证中心独立部署网关统一验签资源服务本地校验签名与标准声明。技术选型上Spring 生态可基于 Spring Authorization Server 自建认证中心[4]也可接入现成 IdP有实测文章给出了 Spring Boot 3.4.x Java 21 环境下接入 MaxKey 的 OIDC 配置其中spring.security.oauth2.client.registration配置client-id、client-secret、authorization-grant-type: authorization_code与scope: openid profile即可走通授权码流程[13]也有教程以 Keycloak 作为授权服务器通过spring-boot-starter-oauth2-client与oauth2Login()让两个独立应用共享登录态[16]。令牌生命周期的推荐口径access_token 有效期 5–15 分钟refresh_token 1–7 天并启用轮换登出采用服务端吊销 refresh_token access_token 进黑名单TTL 剩余有效期的组合避免为追求即时吊销而放弃 JWT 的无状态优势网关与资源服务校验iss、aud、exp并按kid从 JWKS 拉取公钥支持密钥轮换期间双密钥共存。该场景特有的坑前端存 token 的位置。localStorage实现简单但暴露于 XSSHttpOnly Secure Cookie 抗 XSS 但需配套 CSRF 防护与跨域 CORS 配置。没有完美答案需按威胁模型取舍。刷新令牌轮换与复用检测。若发现旧 refresh_token 再次被使用应视为凭证泄露并吊销整个令牌族。JWT 无法主动失效。这是架构级事实不要指望改个配置解决只能用黑名单、版本号声明或短有效期三选一或组合。密钥轮换导致全站 401。轮换必须先发布新公钥、再切换签名、最后下线旧公钥并保留缓冲期。CORS 与重定向 URI 白名单。授权服务器的 redirect_uri 白名单必须精确匹配含尾斜杠差异网关的 CORS 配置不能简单*放行带凭证请求。混淆 access_token 与 ID Token。ID Token 给前端做身份展示access_token 才用于调 API二者不可互换。对于希望降低接入门槛的 Java 团队Sa-Token 提供了框架化的 SSO 方案其官方仓库按前端是否同域 × 后端 Redis 是否共享划分为三种模式前端同域 后端同 Redis 采用共享 Cookie 同步会话前端跨域 后端同 Redis 采用 URL 重定向传播会话前端跨域 后端跨 Redis 采用 Http 请求获取会话[12]。该框架在 2026 年仍保持活跃v1.46.0 覆盖登录、鉴权、分布式 Session、SSO、OAuth2 等模块[11]。需要注意的是GitHub/Gitee 上存在大量第三方镜像分支版本落后于官方仓查阅特性时应以 dromara 官方仓为准。3.3 场景三跨企业集成场景约束信任边界在组织之外对方已有既定 IdP存在合规与审计要求双方变更节奏不同步。推荐路径先问对方 IdP 支持什么再定自己实现什么。对方是传统企业 IdP 且提供 SAML 元数据则走 SAML 2.0对方是现代 IdP 且支持 OIDC则走 OIDC 授权码 PKCE。CAS 基本不用于跨企业场景因为其生态与互操作性远窄于 SAML/OIDC。该场景特有的坑元数据与证书交换流程。交换、校验、轮换、吊销四步都要书面约定测试环境与生产证书必须隔离。签名验证必须开启。SAML 断言与响应的签名验证不能因为联调麻烦而关闭上线前需用未签名/错误签名报文做负向测试。时钟偏移与断言有效期。跨组织服务器时间源不一致是高频故障源需统一 NTP 并明确可容忍偏移量。重放攻击防护。校验InResponseTo、Recipient、NotOnOrAfter等条件保证断言一次性使用。SLO 的责任边界。跨组织场景下谁负责通知谁登出必须写进集成协议否则登出不同步时双方只能互相推诿。最小权限与审计。跨企业账号不应直接映射为内部高权限账号应建立受限的外部身份映射表与登录审计日志。关于开源认证服务器的选型有实战文章在 6 个内部系统统一登录的项目中对 MaxKey 4.1.11、Keycloak 26.x、Casdoor 做了技术栈与能力对比后选择 MaxKey[13]。该对比来自二手文章可作为调研起点但版本与能力描述需在正式评估时自行核验。跨企业集成的具体对接细节本文不做无依据的推演。四、横切章节落地避坑清单以下问题不局限于某一条主线且往往在上线后才暴露。4.1 会话与登出CAS 通过登出回调/过滤器实现 SLO[3][6]OIDC 侧存在 RP-Initiated Logout 等规范机制具体端点名称与行为应对照 OIDC 规范文档核验不要凭记忆拼写端点路径登出后 access_token 是否仍可用取决于是否有黑名单机制需在验收用例中显式断言跨标签页、跨 Web/App 的登录状态同步需要借助 Storage 事件、心跳接口或会话失效码来实现。4.2 令牌生命周期令牌管理的完整链条是签发 → 缓存 → 刷新 → 过期 → 吊销。链条上任何一环的缓存语义错误都会表现为偶发 401。一个跨栈的典型案例是 AWS SDK for Java v2 2.47.1 的修复SSOCredentialsProvider此前在构造时缓存 SSO 访问令牌导致外部执行登录刷新后 SDK 仍使用过期令牌修复后每次凭据刷新时重新解析令牌[14]。Java 业务系统同样存在这类进程内缓存了过期 token的问题尤其是网关侧缓存了 JWKS 或用户信息之后。设计建议黑名单 Key 的 TTL 与 token 剩余有效期对齐refresh_token 采用单次使用 轮换吊销接口要能按用户、按令牌族、按客户端三个粒度操作。4.3 密钥与证书RS256 密钥轮换依赖kid资源方通过 JWKS 端点获取公钥轮换期间新旧公钥并存SAML 证书更换需要双方同步元数据应提前约定提前期与回滚方案私钥、客户端 secret 不进代码仓库、不进日志、不进错误响应。研究资料中的示例代码出现过{noop}明文 secret[5]这是演示写法生产环境必须使用加密存储。4.4 前后端交互细节未认证统一返回 401由前端统一拦截并决定跳转避免后端直接返回 302 到 SPA 中造成页面里嵌页面[18]CORS 白名单精确配置带凭证请求不可使用通配来源Cookie 属性Secure、HttpOnly、SameSite、Domain在目标浏览器与部署域下逐项实测错误码区分未登录“凭证过期”“权限不足”客户端配置错误四类前端才有能力给出正确引导。4.5 可观测性与演练认证与授权链路的故障排查高度依赖日志但日志又最容易泄露凭证。建议审计日志记录userId、clientId、grantType、tokenId或哈希、来源 IP 与结果码绝不记录完整 token 或 secret为 IdP 不可用准备降级预案如紧急放行内网白名单密钥轮换、证书更换必须在测试环境演练全流程后再上生产。问题触发条件常见症状预防措施检查时机Cookie 作用域错误多子域系统登录后其他子系统仍要求登录统一主域 显式 Domain联调首日Ticket/Token 重用一次性票据被缓存间歇性认证失败服务端校验一次性并记录上线前压测JWT 无法吊销账号封禁、登出已登出仍可调 API黑名单 短有效期安全评审密钥轮换未同步证书/密钥更换全站 401kid 双密钥缓冲期轮换演练SLO 不完整登出链路缺回调一处登出其余仍在线覆盖所有 SP 的登出用例验收阶段时钟偏移跨组织/跨机房偶发断言失效NTP 统一 偏移容忍集成联调五、结语一张决策速查卡场景推荐主线首要风险首要检查项同域内网多系统Session 共享Spring Session RedisCookie 作用域、登出不彻底多子域登录态互通 登出全链路前后端分离微服务OAuth2 授权码 OIDC JWT无法主动失效、密钥轮换iss/aud/exp 校验 黑名单策略跨企业集成SAML 2.0 或 OIDC按对方 IdP 决定证书与元数据管理、重放签名校验开启 断言一次性选型的本质不是比较协议的优劣而是把信任边界、凭证形态、登出责任、组织协调成本这四件事放到自己的约束条件下求解。同域内网里强推 SAML 是过度设计跨企业集成里用共享 Cookie 则是边界错配。把登出、吊销、密钥轮换、跨域 Cookie 这些问题在立项阶段定下来远比上线后补救便宜得多。参考资料[1] SSO单点登录完整落地指南OIDC协议选型与SpringBoot认证中心实战CSDNhttps://blog.csdn.net/weixin_42563415/article/details/164482994[2] 单点登录SSO实战从原理到OIDC落地与避坑指南CSDNhttps://blog.csdn.net/weixin_33462927/article/details/166502501[3] Java 单点登录实战一条主线看懂 Session 共享、CAS 与 OAuth2JWT掘金https://juejin.cn/post/7686534839904206888[4] Spring SecurityOAuth2JWT实现轻量级单点登录CSDNhttps://blog.csdn.net/weixin_30512965/article/details/165218927[5] Spring Security OAuth2 单点登录与 JWT 资源服务器实战CSDNhttps://blog.csdn.net/weixin_33842304/article/details/92263577[6] 【Cas客户端接入】SpringbootSpring security接入cas实现单点登录SSO、单点登出SLO掘金https://juejin.cn/post/7409866963982794787[7] 【Spring Security系列】10分钟实现 SpringSecurity CAS 完美单点登录方案掘金https://juejin.cn/post/7436272415436079156[8] 使用CASrediscookies实现单点登录SSO掘金https://juejin.cn/post/6979507175827865607[9] 微服务——SSO 统一登录架构JWT网关、双令牌、RBAC掘金https://juejin.cn/post/7669268061263609919[10] 单点登录实战同端同账号互踢下线的最佳实践Java 实现掘金https://juejin.cn/post/7583226204036775977[11] Sa-Token v1.46.0 详解开源一站式 Java 权限认证框架的登录、鉴权、SSO 与 OAuth2 实战指南CSDNhttps://blog.csdn.net/gitblog_00893/article/details/155588423[12] Sa-Token 开源项目SSO 三种模式说明GitHubhttps://github.com/thorode/Sa-Token官方仓地址https://gitee.com/dromara/sa-token[13] Spring Boot 接入 MaxKey 单点登录6 个内部系统一次登录全通行掘金https://juejin.cn/post/7685936943797239862[14] AWS SDK for Java v2 2.47.x 版本更新全解读TLS 握手超时、SSO 凭据刷新与安全修复CSDNhttps://blog.csdn.net/gitblog_00337/article/details/151638580[15] Sa-Token实现单点登录OAuth 2.0 协议简介 模式配置掘金https://juejin.cn/post/7254927062426402853[16] Java框架快速入门Spring SecurityOAuth2之单点登录SSO实战CSDNhttps://blog.csdn.net/Tyro_java/article/details/165485617[17] Spring Security OAuth2单点登录授权码JWTLDAPCSDNhttps://blog.csdn.net/weixin_34326558/article/details/93183260[18] 前后端分离CAS单点登录处理READMEGiteehttps://gitee.com/leslie8195/front-backend-separation-cas/blob/master/README.md[19] XXL-SSO v2.0.0 发布掘金https://juejin.cn/post/7538665155909107754说明上述资料多为社区实战文章与开源仓库说明其中部分文章的发布时间戳存在标注不一致的情况第三方镜像仓库版本亦可能落后于官方版本文中涉及的版本号、依赖坐标与 API 名称均建议以对应官方文档与实际编译结果为准。文中对落地难度的判断、三类场景的推荐路径以及部分经验公式如OAuth2 管流程 JWT 管凭证属于工程经验总结不构成规范性结论。
返回列表