You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak Admin Client Spring用户删除异常:列表仅100条且角色为空

解决Keycloak用户列表分页与角色获取问题

问题1:用户列表仅返回100条

Keycloak的users().list()方法默认采用分页机制,每页最多返回100条数据。要获取全部用户,必须通过循环分页查询的方式,直到没有新结果返回为止。

问题2:user.getRealmRoles()始终为null

通过list()方法获取的UserRepresentation对象默认不会携带角色信息,需要单独调用Keycloak的角色API,针对每个用户查询其realm角色。

修改后的完整代码

public void deleteWhereNotIn(List<String> keep) {
    int firstResult = 0;
    final int maxResults = 100;
    List<UserRepresentation> users;
    
    // 循环分页拉取所有用户
    do {
        users = keycloak.realm(realm).users().list(firstResult, maxResults);
        
        List<String> remove = new ArrayList<>();
        for (UserRepresentation user : users) {
            // 单独查询用户的realm角色
            List<RoleRepresentation> realmRoles = keycloak.realm(realm)
                    .users().get(user.getId())
                    .roles().realmLevel().list();
            
            // 跳过拥有ADMIN角色的用户
            if (realmRoles != null && realmRoles.stream().anyMatch(role -> role.getName().equals("ADMIN"))) {
                continue;
            }
            
            // 不在保留列表内的用户加入删除队列
            if (keep.stream().noneMatch(uid -> uid.equals(user.getId()))) {
                remove.add(user.getId());
            }
        }
        
        // 执行删除操作
        for (String uid : remove) {
            delete(uid);
        }
        
        firstResult += maxResults;
    } while (!users.isEmpty());
}

补充说明

  • 分页查询时,每次从firstResult位置开始拉取maxResults条数据,直到返回的用户列表为空,代表所有用户已处理完毕。
  • 获取角色时使用roles().realmLevel().list(),并通过role.getName()判断角色名称,避免因RoleRepresentation对象的equals逻辑不匹配导致判断失效。
  • 若担心频繁API调用的性能问题,可以尝试用Keycloak的查询API预先筛选非ADMIN用户(例如users().search()配合角色参数),减少不必要的角色查询次数。

内容的提问来源于stack exchange,提问作者galalem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:07:28