本文对比四个免费候选:两个产品型 IdP(Keycloak、MaxKey),两个框架型方案(Sa-Token、Spring Authorization Server)。四个都是 Apache 2.0,都能私有化,但“装完能用”的程度和 License 之外的成本完全不同。
你的项目是 Spring Boot,这一点决定了判断方式:产品型 IdP 只要支持标准 OIDC,Spring 侧接法基本一致;框架型方案则要自己补认证服务和用户体系。所以先看运维成本和开发量,再看许可证。
版本信息查证于 2026-10-25:Keycloak 26.8.1(2026-10-13)、MaxKey 4.2.0(2026-10-21)、Sa-Token 1.46.0(2026-08-19)、Spring Authorization Server 1.5.8(2026-06-09,独立版最后一个版本,后续并入 Spring Security 7)。上线前请以官方页面为准。
| 你的首要诉求 | 推荐 | 理由 |
|---|---|---|
| 最稳、生态最大、长期维护 | Keycloak | Apache 2.0,26.8.1,Spring 资料最多,发现文档完整 |
| 中文管理后台、CAS/SAML/SCIM 多协议 | MaxKey | Apache 2.0,4.2.0,国产化场景覆盖更全 |
| 团队小、没人愿意维护多套中间件 | Keycloak | 单服务 + 数据库即可,组件比 MaxKey 少 |
| 已有 LDAP/AD、要中文账号生命周期管理 | MaxKey | 组织架构、同步、审计是它的强项 |
| 只想让 Spring Boot 少改代码 | Keycloak | issuer-uri 配完就能跑,角色和注销都有现成能力 |
| 只有 2~5 个内部 Java 系统,只求登录态共享 | Sa-Token | Apache 2.0,接入最简,但走自有 ticket 协议,不是标准 IdP |
| 有用户中心,要把认证能力做进产品 | Spring Authorization Server | Apache 2.0,标准 OIDC,登录页/用户管理/审计全自研 |
产品型 IdP 里只选一个:Keycloak。
中文后台是硬指标、或必须兼容 CAS/SAML 存量系统:MaxKey,但先做 POC。
只服务几个内部 Java 系统:Sa-Token 比上面两个都轻。
要把认证产品化:Spring Authorization Server。
SSO(Single Sign-On,单点登录)解决的是认证集中的问题,不是权限问题。
出现下面任意一种情况,才值得引入:
如果只有一个系统,或者几个系统用户完全不重叠,直接 Spring Security 表单登录就够了。为了两个内部系统上一套 IdP,通常是过度设计;只是要共享登录态的话,第 4 节的 Sa-Token 更合适。
还有一个常见误区:SSO 只负责“你是谁”,不负责“你能干什么”。每个业务系统仍然需要自己的权限模型,不要把全部业务权限都塞进认证中心。
| 维度 | Keycloak 26.8.1 | MaxKey 4.2.0 |
|---|---|---|
| 许可证 | Apache 2.0 | Apache 2.0 |
| 技术栈 | Java / Quarkus | Java / Spring + Tomcat |
| 运行依赖 | 数据库(PostgreSQL 为主) | JDK 21+、MySQL 8.4+、Redis、Tomcat |
| 协议 | OIDC / OAuth2 / SAML 2.0 | OIDC / OAuth2 / SAML 2.0 / CAS / JWT / SCIM 2.0 |
| 管理后台 | 英文为主,可装中文语言包 | 原生中文 |
| 部署形态 | 认证服务 + 数据库 | 认证端、管理端、两个前端 + 数据库 + 缓存 |
| 生态与资料 | 最多 | 明显较少 |
| 适合的团队 | 想要标准、稳定、资料多 | 国内环境、多协议存量系统 |
两个都不是“轻量工具”,而是完整的 IAM 平台。选它们意味着你愿意承担一套基础设施的运维。
这是选型里最容易被含糊过去的一段,尤其在国内语境下,“免费”经常和“社区版”“企业版”“信创版”混在一起。
一句话:免费的是 License,不是运维,也不是开发。
不管选哪个,先确认这三件事:
| 维度 | Keycloak | MaxKey |
|---|---|---|
| 登录方式 | 用户名密码、OTP、WebAuthn、社交登录、身份代理 | 用户名密码、OTP、短信、社交登录、扫码等 |
| 用户来源 | 内置库、LDAP/AD、Kerberos | 内置库、LDAP/AD、SCIM、组织架构同步 |
| 角色模型 | Realm 角色、Client 角色、组合角色、组 | 角色、用户组、组织、应用授权 |
| 角色是否进 Token | 是(realm_access.roles、resource_access) | 否(ID Token 与 UserInfo 都不含角色) |
| 单点注销 | RP-Initiated Logout、Backchannel Logout | RP 发起注销、/sign/force/logout;backchannel 需按版本确认 |
| 多租户 | Realm 隔离;Organizations | 机构(instId)隔离 |
| 中文后台 | 有语言包,但翻译不全 | 原生中文 |
| 授权服务 | 内置 Authorization Services(细粒度策略) | 以 RBAC + 应用授权为主 |
| 扩展方式 | SPI、自定义 Provider、主题 | 适配器、扩展 API、源码定制 |
| 资料可查性 | 高,英文社区大 | 中低,问题更多靠官方文档和源码 |
两个差异值得单独说明。
Keycloak 把角色写进 Token,Spring 侧一个 GrantedAuthoritiesMapper 或 JwtAuthenticationConverter 就能变成 ROLE_xxx。
MaxKey 的 OIDC 实现里,ID Token 只有 sub、iss、aud、iat、exp、jti 这些标准声明;UserInfo 按 scope 返回用户名、姓名、部门、邮箱等属性,没有角色字段。所以:
department 之类的属性做映射;sub(默认取用户名)到业务库查角色;hasRole('admin') 就生效”,在 OIDC 这条路上走不通。end_session_endpoint,Spring 的 OidcClientInitiatedLogoutSuccessHandler 可以直接用;/sign/force/logout?redirect_uri=...,通常要自己写一个 LogoutSuccessHandler 跳过去;上面两个是“产品型 IdP”:装好就有管理台、用户库、登录页、MFA。下面两个是“框架型”:同样免费,但只给你登录态或协议能力,界面和用户体系要自己补。
cn.dev33:sa-token-sso:1.46.0;一句话:它解决“共享登录态”,不解决“对外提供标准身份”。
spring-attic,最后独立版本 1.5.8(2026-06-09),基于 Spring Framework 6.2 / Spring Security 6.5,对应 Spring Boot 3.5;oauth2-authorization-server 模块,Maven 坐标不变,仍是 org.springframework.security:spring-security-oauth2-authorization-server;7.1.2 已发布,7.2.0-RC1 于 2026-10 发布。Boot 3.x 只能用 1.5.x,Boot 4.x 才用 7.x;一句话:免费的是库,不是一套认证服务。
| 维度 | Keycloak | MaxKey | Sa-Token | Spring Authorization Server |
|---|---|---|---|---|
| 类型 | 产品型 IdP | 产品型 IdP | 框架(SSO 模块) | 框架(授权服务器) |
| 装完能用 | 能 | 能 | 要接自己的登录 | 不能,先写一套 |
| 标准 OIDC | 是 | 是,有差异 | 否 | 是 |
| 内建用户与管理台 | 有 | 有 | 无 | 无 |
| 免费边界 | Apache 2.0 全功能 | Apache 2.0 + 商业服务 | Apache 2.0 | Apache 2.0 |
| 主要成本 | 运维 | 运维 + 生态小 | 协议锁定 | 开发量 |
| 适合 | 多系统、第三方 | 国内多协议 | 内部几个 Java 系统 | 认证产品化 |
很多人以为“都支持 OIDC,接法一样”。对两个产品型 IdP 来说方向没错,但落地时差别不小。
yamlspring:
security:
oauth2:
client:
registration:
keycloak:
provider: keycloak
client-id: blog-web
client-secret: ${KEYCLOAK_CLIENT_SECRET}
authorization-grant-type: authorization_code
scope: openid,profile,email
provider:
keycloak:
issuer-uri: http://localhost:8080/realms/blog
realm_access.roles;MaxKey 4.2.0 的发现文档位于 /sign/authz/oauth/v20/.well-known/openid-configuration,而 Spring Security 会把 issuer-uri 拼成 <issuer>/.well-known/openid-configuration,并且要求发现文档里的 issuer 与配置值完全一致。MaxKey 在不带 client_id 参数时返回的 issuer 是带 /maxkey 的上下文形态,两边对不上,所以直接用 issuer-uri 会报 issuer 不匹配。
实际可行的做法是显式配置端点:
yamlspring:
security:
oauth2:
client:
provider:
maxkey:
authorization-uri: http://localhost:9527/sign/authz/oauth/v20/authorize
token-uri: http://localhost:9527/sign/authz/oauth/v20/token
user-info-uri: http://localhost:9527/sign/api/connect/v10/userinfo
jwk-set-uri: http://localhost:9527/sign/authz/oauth/v20/jwks
此外还有三个默认值必须先改,否则登录大概率失败:
read:要手动加上 openid、profile、email,否则拿不到 ID Token;RS256;NORMAL(JSON)。这些都是配置层面的成本,不是写代码的成本,但第一次接的人很容易卡在这儿。
登录、Session、权限控制、注销这些 Spring 侧结构可以复用,但不能只改 issuer-uri 就切换。从 Keycloak 换到 MaxKey,至少要改:
如果目标是“把认证能力做进产品”,下面这棵树不适用,直接看 Spring Authorization Server。
text只有 2~5 个内部 Java 系统,且不接第三方? ├─ 是 → Sa-Token(最轻,但锁在自有协议上) └─ 否 → 有中文管理后台的硬性要求吗? ├─ 有 → 需要 CAS/SAML/SCIM 等存量协议吗? │ ├─ 需要 → MaxKey(先 POC) │ └─ 不需要 → 能接受多维护 MySQL + Redis + Tomcat 吗? │ ├─ 能 → MaxKey │ └─ 不能 → Keycloak └─ 没有 → 团队更看重资料多、踩坑少吗? ├─ 是 → Keycloak └─ 否 → 两个都可以,按运维习惯选
更直接的判断:
如果你倾向 MaxKey,不要只看官网截图,至少验证这 8 件事。
openid,profile,email 后,ID Token 的 alg 是不是 RS256,aud 是否等于 clientId。preferred_username 取的是显示名,不是登录名)。/sign/force/logout 是否按预期清理 IdP 会话并跳回业务系统。再加一条:退出预案。对外只暴露标准 OIDC,不要把业务代码绑死在某个产品的 SDK 上。
这不是说 MaxKey 不好。它在中文后台、多协议兼容、国产化场景上确实有优势,Apache 2.0 也足够干净。问题在于:它的生态和“Spring Boot 开箱即用”的程度不如 Keycloak,你需要为这些差异付出配置和排障成本。
Sa-Token 和 Spring Authorization Server 同样免费,但没有放进本系列的实战:前者走自有协议,后者要自己补齐用户体系。如果你的场景已经明确落在“内部几个 Java 系统”或“认证产品化”上,直接按第 4 节选就行,不必先跟着跑 Keycloak。
本系列的选择是:
接下来的两篇:
SecurityConfig、角色映射、单点注销;本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!