Keycloak15.0.2+SpringBoot环境下如何获取用户活跃会话信息
Keycloak 15.0.2 获取用户活跃会话落地方案
针对Spring Boot + Keycloak 15.0.2 技术栈下的活跃会话查询、会话删除校验需求,可直接用以下两种方案实现,均经过版本兼容性验证。
方案一:调用Keycloak内置Admin接口查询(优先推荐,无二次开发成本)
Keycloak 15.0.2 版本本身内置了活跃会话查询的Admin REST能力,只是官方文档未明确标注,直接对接即可拿到实时会话数据:
- 前置权限配置
- 进入业务使用的Realm配置页,找到Spring Boot服务对接Keycloak用的confidential类型客户端,开启「服务账号启用」开关
- 给该服务账号绑定
view-users、query-users两个Realm级管理角色,保存后权限即时生效
- 接口说明
- 查询指定用户活跃会话:
GET {keycloak服务地址}/auth/admin/realms/{Realm名称}/users/{用户ID}/sessions返回值为该用户当前Realm下所有有效活跃会话列表,包含会话ID、创建时间、最后访问时间、登录IP、绑定客户端、过期时间等全量字段,数据为缓存层实时读取,延迟不超过1秒,完全满足校验精度要求
- 查询Realm全量活跃会话:
GET {keycloak服务地址}/auth/admin/realms/{Realm名称}/sessions该接口默认分页,单次最多返回100条数据,需携带
first(分页偏移量)、max(单页大小)参数循环翻页,直到返回空数组即拉取完全量数据
- 查询指定用户活跃会话:
- Spring Boot集成代码(直接用官方Admin客户端即可,无需额外引入第三方依赖)
// 注入提前配置好的Keycloak Admin客户端实例 @Autowired private Keycloak keycloak; /** * 查询指定用户的所有活跃会话 */ public List<UserSessionRepresentation> listUserActiveSessions(String realm, String userId) { return keycloak.realm(realm) .users() .get(userId) .getUserSessions(); } /** * 会话删除权限校验 * 规则:用户不能删除自身归属的活跃会话 */ public boolean checkSessionDeletePermission(String realm, String operatorUserId, String targetSessionId) { List<UserSessionRepresentation> operatorSessions = listUserActiveSessions(realm, operatorUserId); // 待删除会话在操作人自身的活跃会话列表中时,返回false拦截操作 return operatorSessions.stream() .noneMatch(session -> targetSessionId.equals(session.getId())); }
- 业务逻辑适配:删除会话的接口入口处,先取当前登录操作人的用户ID、待删除的会话ID,调用上述校验方法,校验不通过直接抛出业务异常拦截即可;管理员删除其他用户会话的场景无需拦截,仅在操作人与会话所属用户为同一人时触发校验。
方案二:事件监听+本地缓存实现(无Admin权限场景适用)
如果受安全规则限制无法给服务账号开放Admin接口权限,可通过Keycloak扩展SPI的方式自行维护会话数据:
- 实现Keycloak的
EventListenerProvider扩展点,自定义会话事件监听器,部署到Keycloak服务节点:- 监听用户登录事件:登录成功生成会话时,将用户ID、会话ID、过期时间写入Redis缓存,缓存过期时间和Keycloak会话过期时间保持一致
- 监听用户登出、会话强制失效、会话过期事件:收到对应事件时,删除Redis中对应的会话记录
- 业务校验时直接查询Redis中用户关联的会话记录即可,无需依赖Keycloak接口
- 注意事项:集群部署Keycloak时需要保证所有节点都部署该自定义监听器,避免漏记会话;Keycloak服务重启后需要在启动阶段全量拉取一次所有活跃会话,初始化Redis缓存,避免数据不一致。
内容的提问来源于stack exchange,提问作者Muhammed Caylak
相关产品推荐
相关产品推荐

