如何在两个Keycloak实例间同步指定用户(含凭证)实现跨区域高可用
Keycloak跨实例带自定义属性筛选的用户同步实现方案
完全可以通过Keycloak原生的API、SPI能力实现需求,不需要直接操作数据库,以下是具体可行的落地方案:
首选方案:基于Admin REST API实现可控同步
这是开发成本最低、稳定性最高的实现方式,完全覆盖你的筛选、凭证同步需求:
- 自定义属性筛选:调用源实例的
GET /{realm}/users接口,通过q参数传入自定义属性的筛选规则,比如要筛选region属性为cn-north-1的用户,直接传q=region:cn-north-1即可,还可以搭配createdTimestamp、lastModifiedTimestamp参数做增量同步,避免每次全量拉取数据。 - 凭证同步:只要两个Keycloak实例配置完全一致的密码哈希策略(包括算法类型、迭代次数、盐值长度、哈希编码格式),就可以直接从源实例接口拉取用户的已哈希凭证串,调用备实例的
PUT /{realm}/users/{id}/reset-password接口直接写入哈希值,不需要获取用户明文密码即可完成凭证同步。 - 实时性优化:可以在源实例通过事件监听SPI自定义事件推送逻辑,当用户发生创建、属性修改、密码更新、删除等操作时,直接将事件推送到中间消息队列,备端消费事件触发同步,相比定时轮询可以把同步延迟控制在秒级。
- 权限要求:用于调用API的服务账号仅需要分配
view-users、manage-users、manage-passwords三个权限即可,遵循最小权限原则降低安全风险。
备选方案:自定义用户存储SPI实现联邦
如果不想在两个实例各存一份用户数据,可以给备用实例开发自定义用户存储SPI,直接对接源实例的用户能力,同时在本地做热点数据缓存。当源实例故障时,备实例自动切换为读取本地缓存的用户数据对外提供服务,这个方案的同步延迟更低,但开发成本比API方案高30%~50%,适合对RTO要求极高的场景。
为什么不建议直接操作数据库
和你的顾虑一致,Keycloak的库表结构会随版本迭代发生调整,直接读写数据很容易遗漏关联表数据(比如用户和角色、客户端、组的关联关系,用户会话数据等),而且直接修改数据库不会触发Keycloak的内部缓存刷新,会出现数据不一致、前端展示异常的问题,仅建议作为极端故障恢复的最后备用方案。
内容的提问来源于stack exchange,提问作者Netanel Albert
相关产品推荐
相关产品推荐

