如何通过Keycloak SPI的EventListenerProvider获取用户在线/离线会话
Keycloak用户/组级同步最大会话限制:解决UserSessionProvider无法获取会话的问题
针对你遇到的在EventListenerProvider中调用UserSessionProvider无法获取用户会话的问题,以下是几个非异步的解决思路:
1. 切换监听的事件类型
登录事件(如LOGIN_SUCCESS)触发时,新的用户会话可能尚未完成持久化操作,此时调用UserSessionProvider自然拿不到数据。建议监听USER_SESSION_CREATED事件——这个事件是在用户会话创建并保存到存储后触发的,能确保会话已存在。
2. 正确获取会话提供者实例
必须从当前事件关联的KeycloakSession中获取UserSessionProvider,避免使用错误的会话实例。示例代码:
// 在EventListenerProvider的onEvent方法中 RealmModel realm = session.getContext().getRealm(); UserModel user = session.users().getUserById(realm, event.getUserId()); if (user == null) return; UserSessionProvider sessionProvider = session.getProvider(UserSessionProvider.class);
3. 适配不同Keycloak版本的API
不同版本的UserSessionProvider方法存在差异,需针对性调整:
- Keycloak 11.0.3:使用
getUserSessions方法获取会话列表
// includeOffline:是否包含离线会话;clientSpecific:是否仅针对特定客户端 List<UserSessionModel> sessions = sessionProvider.getUserSessions(realm, user, true, false); int activeCount = (int) sessions.stream().filter(UserSessionModel::isStarted).count();
- Keycloak 19.0.1+/20.0.1:使用流式API
getUserSessionsStream获取会话
Stream<UserSessionModel> sessionsStream = sessionProvider.getUserSessionsStream(realm, user, true); int activeCount = (int) sessionsStream.filter(UserSessionModel::isStarted).count();
也可以通过UserSessionManager直接获取:
UserSessionManager sessionManager = session.sessions(); Stream<UserSessionModel> sessions = sessionManager.getUserSessions(realm, user);
4. 强制刷新事务(可选)
如果切换事件类型后仍无法获取会话,可在获取会话前手动刷新事务,确保会话已写入存储:
session.getTransaction().flush();
5. 集群环境下的会话共享配置
如果Keycloak部署在集群环境,默认本地会话存储可能无法跨节点同步。需配置共享会话存储(如JDBC数据库、Infinispan集群),确保所有节点能读取到完整的用户会话数据。
实现会话限制的示例逻辑
拿到用户会话列表后,即可实现最大会话限制:
final int MAX_SESSIONS = 2; // 自定义最大会话数 if (activeCount > MAX_SESSIONS) { // 找到最早的活跃会话并销毁 UserSessionModel oldestSession = sessions.stream() .filter(UserSessionModel::isStarted) .sorted(Comparator.comparing(UserSessionModel::getStart)) .findFirst() .orElse(null); if (oldestSession != null) { sessionProvider.removeUserSession(realm, oldestSession); } }
内容的提问来源于stack exchange,提问作者user1767316
相关产品推荐
相关产品推荐

