Spring Boot资源服务器共享Keycloak用户表的合理性及方案问询
Keycloak用户表与业务用户数据存储的最佳实践建议
直接把Keycloak用户表和你的业务用户数据放在同一张表里,属于不良实践,核心原因如下:
- Keycloak的表结构由自身维护,版本升级时大概率会修改字段、调整表结构,甚至删除旧字段。你自行添加的业务字段很可能在升级时被覆盖或丢失,风险极高。
- 认证数据(Keycloak负责的身份信息)和业务数据(你的业务逻辑专属数据)的访问模式完全不同,混存会增加数据库查询复杂度,后续性能优化也难以开展。
- 违背单一职责原则:Keycloak专注于身份认证与基础用户身份管理,业务数据属于业务域范畴,分开维护更利于扩展和问题排查。
推荐的处理方式
1. 业务数据单独建表存储
专门创建业务用户表(比如命名为business_users),通过Keycloak用户唯一ID(即JWT Token中的sub字段,优先用这个,别用邮箱,因为用户可能修改邮箱)与Keycloak用户表关联。业务表仅存储业务相关数据:首次登录时间、用户帖子关联信息、业务专属权限配置等。
2. 首次登录时初始化业务数据
用户首次登录Spring Boot资源服务器时,从Authentication对象中提取Keycloak用户信息,再检查业务表是否存在该用户:
- 若不存在,插入新记录并初始化首次登录时间等基础业务数据。
- 若已存在,更新最后登录时间这类需要实时同步的字段。
简单代码示例:
@Service public class UserSyncService { @Autowired private BusinessUserRepository businessUserRepository; public void syncUser(Authentication auth) { KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) auth; KeycloakPrincipal<KeycloakSecurityContext> principal = (KeycloakPrincipal<KeycloakSecurityContext>) token.getPrincipal(); String keycloakUserId = principal.getKeycloakSecurityContext().getToken().getSubject(); String email = principal.getKeycloakSecurityContext().getToken().getEmail(); Optional<BusinessUser> existingUser = businessUserRepository.findByKeycloakUserId(keycloakUserId); if (existingUser.isEmpty()) { BusinessUser newUser = new BusinessUser(); newUser.setKeycloakUserId(keycloakUserId); newUser.setEmail(email); newUser.setFirstLoginTime(LocalDateTime.now()); newUser.setLastLoginTime(LocalDateTime.now()); businessUserRepository.save(newUser); } else { BusinessUser user = existingUser.get(); user.setLastLoginTime(LocalDateTime.now()); businessUserRepository.save(user); } } }
3. 触发同步的时机
- 用Spring Security的
AuthenticationSuccessHandler,每次用户登录成功后自动执行同步逻辑,省心高效。 - 也可在需要获取业务数据的接口中先检查,若未找到业务用户则初始化,适合访问频率较低的场景。
4. 优化:避免重复初始化
在Keycloak的用户属性中添加business_initialized标记,完成业务数据初始化后将该标记设为true,后续登录先检查此标记,即可避免重复执行初始化逻辑。
额外提醒
- 绝对不要直接修改Keycloak的数据库表,所有业务相关扩展都放在自己的业务库中。
- 若需在Keycloak中展示少量业务数据,可使用Keycloak的用户属性功能存储,但大量业务数据仍需放在业务库。
- 当Keycloak中的用户基础信息(如邮箱、用户名)变更时,需同步到业务表——可通过Keycloak的Webhook触发同步,或设置定时任务定期拉取更新。
内容的提问来源于stack exchange,提问作者ZZBL
相关产品推荐
相关产品推荐

