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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 06:49:58