WebSocket网站通知实现:SimpUserRegistry.getUsers()返回空列表问题
解决SimpUserRegistry.getUsers()返回空列表的问题
问题原因
SimpUserRegistry仅跟踪经过认证/关联身份的WebSocket连接用户。如果客户端连接时没有传递用户身份信息,或者未通过Spring Security完成认证,getUsers()就会返回空列表。
解决方案
方案1:手动通过握手拦截器绑定用户标识(无需完整认证)
修改WebSocketConfig,添加握手拦截器,从请求中获取用户标识并绑定到连接:
@Configuration @RequiredArgsConstructor @EnableWebSocket @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic", "/user"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws") .setAllowedOriginPatterns("*") .addInterceptors(new HandshakeInterceptor() { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { // 从请求参数中获取前端传递的用户标识 ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; String username = servletRequest.getServletRequest().getParameter("username"); if (username != null) { // 绑定用户身份到WebSocket连接 attributes.put("user", (Principal) () -> username); } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {} }); } }
前端SockJS连接时,携带用户标识参数:
// 替换为实际的用户唯一标识(如用户ID、用户名) const username = "user123"; const socket = new SockJS(`/ws?username=${username}`); const stompClient = Stomp.over(socket); stompClient.connect({}, (frame) => { // 订阅消息逻辑 });
方案2:通过Spring Security认证关联用户(需登录)
如果你的系统需要用户登录,配置Spring Security后,WebSocket连接会自动关联已认证的用户,SimpUserRegistry即可获取到用户列表。
添加Spring Security配置类:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .formLogin(form -> form.permitAll()) .logout(logout -> logout.permitAll()); return http.build(); } }
用户登录后,WebSocket连接会自动携带认证信息,此时调用getUsers()即可返回已连接的认证用户。
验证
调用/notifications/getUser接口时,控制台会输出已连接的用户标识,simpUserRegistry.getUsers()不再为空。
内容的提问来源于stack exchange,提问作者KripDo
相关产品推荐
相关产品推荐

