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

如何在WebSocket控制器中获取当前已登录的认证用户

问题原因

WebSocket STOMP协议的握手阶段默认不会自动同步Spring Security的HTTP认证上下文到WebSocket会话中,导致后续消息处理时无法获取到已认证的Principal对象。


解决步骤

1. 修改WebSocket配置,添加认证信息同步逻辑

修改你的WebSocketConfig类,增加握手拦截器、入站通道拦截器,配置用户目的地前缀:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/connect")
                // 生产环境请替换为具体前端域名,不要使用通配符*
                .setAllowedOrigins("*")
                // 同步HTTP Session中的认证信息到WebSocket会话
                .addInterceptors(new HttpSessionHandshakeInterceptor());
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 配置用户消息前缀,配合convertAndSendToUser使用
        registry.setUserDestinationPrefix("/user");
        registry.enableSimpleBroker("/topic/messages", "/user");
        registry.setApplicationDestinationPrefixes("/ws");
    }

    // 无状态JWT认证场景可添加此拦截器,从请求头解析token完成认证
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    // 从连接头获取token,自行完成认证后设置用户信息
                    // String token = accessor.getFirstNativeHeader("Authorization");
                    // Authentication auth = authenticationManager.authenticate(自定义认证对象);
                    // accessor.setUser(auth);
                    // SecurityContextHolder.getContext().setAuthentication(auth);
                }
                return message;
            }
        });
    }
}

2. 调整Spring Security配置

确保WebSocket端点的权限、跨域规则符合要求:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                // 允许已认证用户访问WebSocket端点
                .requestMatchers("/connect").authenticated()
                .anyRequest().authenticated()
            )
            // 跨域配置要和WebSocket配置保持一致
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            // Session策略根据你的认证方式调整,Cookie认证保留默认IF_REQUIRED即可
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 生产环境替换为具体前端域名
        configuration.setAllowedOrigins(List.of("*"));
        configuration.setAllowedMethods(List.of("*"));
        configuration.setAllowedHeaders(List.of("*"));
        // Cookie认证场景需要开启允许携带凭证
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

3. 前端连接时携带认证凭证

  • Cookie认证场景必须开启withCredentials,才能将Cookie中的认证信息传递到后端
  • Token认证场景需要在STOMP连接头中携带认证Token
import SockJS from 'sockjs-client';
import { Stomp } from '@stomp/stompjs';

const socket = new SockJS('http://你的后端地址/connect', {}, {
  withCredentials: true // Cookie认证必须开启
});
const stompClient = Stomp.over(socket);

stompClient.connect({
  // Token认证场景在此处添加认证头
  // 'Authorization': 'Bearer ' + 你的Token
}, (frame) => {
  console.log('连接成功');
  stompClient.send("/ws/start", {}, {});
});

验证

完成上述配置后,@MessageMapping标注方法中的Principal入参即可正常获取,也可以通过SecurityContextHolder.getContext().getAuthentication()拿到认证信息。
注意:如果开启了allowCredentials=true,WebSocket和Security的跨域配置中不能使用通配符*作为允许来源,必须填写具体的前端域名

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:36:03