Keycloak 身份和访问管理
什么是 Keycloak?
Keycloak 是一款开源的身份和访问管理(IAM)解决方案,由 Red Hat 维护。它旨在为现代应用程序和服务提供开箱即用的认证和授权功能,无需从头构建复杂的用户体系。通过 Keycloak,开发者可以快速为任何基于 Web、移动端或 REST 的应用程序添加单点登录(SSO)、社交登录、基于角色的访问控制等能力,同时支持标准协议如 OpenID Connect (OIDC)、OAuth 2.0 和 SAML 2.0。
核心优势
- 开箱即用的功能:提供登录、注册、忘记密码、邮箱验证、双因素认证等完整用户界面。
- 协议支持:全面支持 OIDC、OAuth 2.0 和 SAML 2.0,适配绝大多数应用场景。
- 集中化管理:一个管理控制台即可管理所有用户、角色、权限和应用。
- 可扩展和定制:通过 SPI 接口自定义用户存储、主题、身份源等。
- 高可用与集群:支持部署集群,适应企业级高并发需求。
核心概念详解
Realm(域)
Realm 是 Keycloak 中的最高逻辑隔离单元,每个 Realm 拥有一套独立的用户、角色、客户端和配置。可以理解为“租户”。一个 Keycloak 服务器可以托管多个 Realm,它们之间完全隔离。通常,每个组织或一个应用生态创建一个 Realm。
Client(客户端)
Client 代表一个需要被 Keycloak 保护的应用或服务。客户端有两种类型:
- confidential(机密客户端):后端服务,可以安全保存密钥,如 Spring Boot 应用。
- public(公开客户端):前端应用或移动端,无法安全保存密钥,如 JavaScript SPA 或 Android 应用。
客户端通过不同协议(OIDC、SAML)与 Keycloak 通信。
User(用户)
用户是最终登录访问应用的实体。用户拥有基本属性(用户名、邮箱、名字等),并可以关联角色和组。Keycloak 内置用户存储,也可以对接外部目录服务(LDAP、Active Directory)或自定义用户存储。
Role(角色)
角色是一组权限的命名集合,用于实现基于角色的访问控制(RBAC)。角色分为两种:
- Realm 角色:全局角色,作用于整个 Realm。
- Client 角色:特定于某个客户端,用于该应用内部的细粒度授权。
Group(组)
组用于将用户归类,一个组可以包含多个用户,并且可以拥有自己的角色。组内用户自动继承组的角色,简化权限批量分配。
安装与启动
使用 Docker 快速部署
本地开发最便捷的方式是通过 Docker 启动:
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev
这会将 Keycloak 运行在 http://localhost:8080,同时创建一个 admin/admin 的管理员账户。
访问管理控制台
打开浏览器访问 http://localhost:8080/admin,使用管理员凭证登录。至此,管理控制台准备就绪。
实战:创建第一个 Realm 和客户端
创建 Realm
- 登录管理控制台后,悬停在左上角的 “Master” 下拉菜单,点击 “Create Realm”。
- 输入 Realm 名称,例如
myapp,然后点击 “Create”。 - 新创建的 Realm 会成为当前活动 Realm,后续所有配置都将在这个隔离空间内进行。
创建 OpenID Connect 客户端
- 在左侧导航栏点击 “Clients”,然后点击 “Create client”。
- 客户端类型选择
OpenID Connect,Client ID 填写my-app-client,点击 “Next”。 - 确保 “Standard flow” 已启用。
- 点击 “Save” 保存。
配置客户端重定向 URI
保存后进入客户端设置页,向下滚动到 “Access settings” 区域:
- Valid redirect URIs:填写应用接收授权码的 URL,例如
http://localhost:3000/*(前后端分离的前端地址)或http://localhost:8081/login/oauth2/code/keycloak(Spring Boot 应用默认路径)。需要支持通配符*。 - Valid post logout redirect URIs:填写登出后的跳转地址,如
http://localhost:3000。 - Web origins:设置允许跨域的来源地址,一般与前端地址相同。
点击 “Save” 保存。
用户、角色与权限配置
创建用户与设置密码
- 左侧菜单选择 “Users”,点击 “Add user”。
- 仅需要填写 Username,其他可选。
- 创建后,进入用户详情页,切换到 “Credentials” 标签。
- 点击 “Set password”,输入密码并关闭 “Temporary” 开关(首次登录不强制修改密码),然后保存。
创建角色(Realm 角色)
- 选择 “Roles” 菜单,点击 “Create realm role”。
- 输入角色名称,如
USER,可选填写描述,然后保存。 - 创建另一个角色,如
ADMIN。
将角色分配给用户
- 回到 “Users”,选择之前创建的用户。
- 进入 “Role mapping” 标签,点击 “Assign role”。
- 从列表中选择刚才创建的
USER角色并分配。用户可同时拥有多个角色。
应用集成示例
保护 Spring Boot 应用(OIDC)
在 application.properties 中配置:
spring.security.oauth2.client.registration.keycloak.client-id=my-app-client
spring.security.oauth2.client.registration.keycloak.client-secret=<your-client-secret>
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri=http://localhost:8081/login/oauth2/code/keycloak
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/realms/myapp
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
Client secret 可在客户端详情页的 “Credentials” 标签中获取。
依赖配置(基于 Spring Boot 3.x):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
安全配置示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(Customizer.withDefaults());
return http.build();
}
}
启动应用,访问受保护的资源时,会自动重定向到 Keycloak 登录页面。
在 JavaScript 单页应用中使用 Keycloak
安装 Keycloak JS 适配器:
npm install keycloak-js
初始化示例:
import Keycloak from 'keycloak-js';
const keycloak = new Keycloak({
url: 'http://localhost:8080',
realm: 'myapp',
clientId: 'my-app-client' // 必须是 public 类型的客户端
});
try {
const authenticated = await keycloak.init({ onLoad: 'login-required' });
console.log('Authenticated:', authenticated);
// 获取令牌
console.log(keycloak.token);
} catch (error) {
console.error('Failed to initialize', error);
}
在 Keycloak 管理控制台确保客户端类型为 public,且 “Standard flow” 已开启,同时正确配置了 Web origins 和 Redirect URIs。
身份代理与社交登录
Keycloak 支持将外部身份提供者(IdP)作为用户登录的另一种方式,常见如 Google、GitHub、Facebook 或企业自有的 OIDC/SAML IdP。
配置 GitHub 社交登录
- 在 Realm 下选择 “Identity providers”,点击 “GitHub”。
- 填写从 GitHub OAuth App 获得的 Client ID 和 Client Secret。
- 其他选项保持默认,点击 “Save”。
之后在 Keycloak 的登录页便会自动出现 GitHub 登录按钮,首次使用的新用户会被自动创建在 Keycloak 中。
进阶主题
自定义登录主题
Keycloak 的界面可以通过主题进行深度定制。路径位于 Keycloak 安装目录的 themes/ 下,每个主题包含 Freemarker 模板、CSS、JS 等资源。
- 复制基础主题
base或keycloak目录为新的文件夹mytheme。 - 在 Realm 设置 → “Themes” 标签中选择 “login theme” 为
mytheme。 - 修改主题中的样式或模板,重启 Keycloak 或部署即可生效。
对于 Docker 部署,需将主题文件夹挂载到容器内部。
使用 Keycloak REST API
Keycloak 提供全面的管理 REST API,可使用管理员令牌进行自动化操作。常用端点示例:
- 获取管理员 Token(需在 Master 或其他 Realm 上创建对应客户端,授权类型为
client_credentials):
curl -X POST -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" http://localhost:8080/realms/master/protocol/openid-connect/token
- 使用 Token 创建用户:
curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"username":"testuser","enabled":true,"credentials":[{"type":"password","value":"test123","temporary":false}]}' \
http://localhost:8080/admin/realms/myapp/users
完整的 API 文档可在 Keycloak 服务器自带的 /resources/ 路径下查看,或访问官方文档。通过 API 可以实现用户、角色、组的批量管理和 CI/CD 集成。
总结
Keycloak 以最少的代码侵入实现了企业级的身份和访问管理。本文从核心概念、安装部署、客户端配置、用户角色管理,到与 Spring Boot 和单页应用的集成,以及高级功能如社交登录和主题定制,覆盖了大多数典型使用场景。掌握以上内容后,你可以为几乎任何应用快速搭建认证与授权基础设施,将精力集中在核心业务开发上。