Keycloak 单点登录(SSO)部署是企业统一身份认证的基础设施建设。随着内部系统增多,每套系统独立维护账号密码会放大弱口令与凭证泄露风险。Keycloak 作为开源 IAM 平台,通过 OIDC/SAML 协议让用户登录一次即可访问全部接入应用,同时提供 MFA、会话策略等安全能力。本教程演示完整部署与接入流程。
适用场景
- 企业存在多套 Web 应用,需要统一登录入口与账号体系
- 需要为第三方应用提供 OIDC 或 SAML 身份认证
- 需要对不同角色用户实施差异化访问控制
- 需要集中管理密码策略、会话超时与多因素认证
前置条件
- 一台 Linux 服务器(建议 2C4G 以上),安装 Docker 与 Docker Compose
- 已规划域名并配置 DNS 解析,如
sso.example.com - 已有 TLS 证书(Keycloak 生产环境要求 HTTPS)
- 了解 OIDC 基本概念:Client、Realm、Access Token
原理说明
Keycloak 的核心概念是 Realm(领域),一个 Realm 相当于一个独立的租户,包含用户、客户端与角色。应用作为 Client 注册到 Realm 中,用户访问应用时被重定向到 Keycloak 登录页,认证成功后 Keycloak 签发 ID Token 与 Access Token,应用通过 JWKS 公钥验签即可信任用户身份。相比每个应用各自实现登录,SSO 将认证逻辑收敛到单一平台,便于统一实施密码策略、MFA 与审计。
操作步骤
步骤一:Docker Compose 部署 Keycloak
创建 docker-compose.yml:
version: "3.8"
services:
keycloak:
image: quay.io/keycloak/keycloak:24.0
container_name: keycloak
command: start --optimized
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://db:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: Kc@2026!StrongPass
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: Admin@2026!StrongPass
KC_HOSTNAME: sso.example.com
KC_HTTPS_CERTIFICATE_FILE: /certs/fullchain.pem
KC_HTTPS_CERTIFICATE_KEY_FILE: /certs/privkey.pem
ports:
- "8443:8443"
volumes:
- /etc/letsencrypt/live/sso.example.com:/certs:ro
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: Kc@2026!StrongPass
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
启动并验证:
docker compose up -d
# 等待启动完成后访问管理控制台
curl -k -s -o /dev/null -w "%{http_code}" https://127.0.0.1:8443/realms/master
步骤二:创建 Realm 与客户端
在管理控制台 https://sso.example.com:8443 使用 admin 登录后:
- 点击左上角 master 下拉,选择 Create realm,名称填写
corp,点击 Create - 进入 Clients,点击 Create client,Client ID 填写
erp-web,Client type 选择OpenID Connect - 在 Capability config 中勾选 Standard flow(授权码模式),Redirect URIs 填写
https://erp.example.com/callback - 保存后切换到 Credentials 页,复制 Client secret 备用
步骤三:创建测试用户与角色
# 通过 Admin REST API 创建用户(替换 TOKEN 为客户端凭证获取的访问令牌)
curl -X POST "https://sso.example.com:8443/admin/realms/corp/users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username":"zhangsan","enabled":true,"email":"zhangsan@example.com","credentials":[{"type":"password","value":"User@2026!","temporary":false}]}'
同时可在管理界面 Realm roles 中创建 erp-admin 角色,并在用户详情中为用户分配该角色。
步骤四:应用侧接入 OIDC
以常见的前端接入为例,使用 oidc-client-js 初始化:
import { UserManager } from "oidc-client-ts";
const mgr = new UserManager({
authority: "https://sso.example.com:8443/realms/corp",
client_id: "erp-web",
client_secret: "你的ClientSecret",
redirect_uri: "https://erp.example.com/callback",
response_type: "code",
scope: "openid profile email",
});
// 触发登录跳转
mgr.signinRedirect();
// 回调页完成令牌换取
mgr.signinRedirectCallback().then(user => {
console.log("登录用户:", user.profile.preferred_username);
});
配置验证
# 验证 Realm 公开配置可访问(OIDC 发现端点)
curl -s https://sso.example.com:8443/realms/corp/.well-known/openid-configuration | python3 -m json.tool | head -20
# 验证 JWKS 公钥端点可正常返回
curl -s -o /dev/null -w "%{http_code}" https://sso.example.com:8443/realms/corp/protocol/openid-connect/certs
# 未登录访问受保护应用应被重定向到 Keycloak 登录页
curl -s -o /dev/null -w "%{redirect_url}" http://erp.example.com/
常见问题
FAQ 1:客户端获取令牌时提示 invalid_client?
通常原因是 Client secret 不匹配或客户端未启用相应流程。检查 Clients → erp-web → Credentials 中的 secret 是否与代码一致,并在 Client authentication 处确认已开启。若是公开客户端(无 secret),则不能配置 client_secret。
FAQ 2:Keycloak 生产环境如何避免默认管理员风险?
建议:创建独立的 Realm 管理员而非直接使用 master 域 admin;为 admin 开启 MFA(Authentication → Required actions → Configure OTP);将管理控制台仅绑定内网地址或用防火墙限制来源 IP。定期检查 Realm 的会话数与异常登录日志。
总结
Keycloak 将企业身份认证收敛为单点登录统一入口,通过 Realm 隔离租户、Client 接入应用、角色控制权限,配合 OIDC 标准协议实现与任意语言的集成。生产部署务必使用 HTTPS、强密码并启用 MFA,同时做好 PostgreSQL 数据备份。接入新应用时遵循「最小权限」原则,仅分配必要的 scope 与角色,可显著降低凭证泄露与横向移动风险。