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

Spring STOMP添加CSRF令牌遇MissingCsrfTokenException报错求助

解决STOMP CONNECT时CSRF令牌验证失败(会话未找到)的问题

这个问题我之前帮好几个开发者排查过,核心原因是CSRF令牌和HttpSession的绑定时机不匹配——你在发送STOMP CONNECT帧的时候,对应的HttpSession还没在服务器端建立,导致Spring Security找不到令牌关联的会话,从而抛出MissingCsrfTokenException。

下面是具体的排查和解决步骤:

1. 先明确CSRF令牌的绑定逻辑

Spring Security的CSRF令牌是和HttpSession绑定存储的,默认会把令牌值通过XSRF-TOKEN Cookie返回给客户端(需要配置CookieCsrfTokenRepository.withHttpOnlyFalse()才能让前端读取)。如果客户端发送的令牌对应的会话不存在,服务器就会报错“会话未找到”。

2. 确保客户端发送CONNECT前已建立HttpSession

很多开发者犯的错是:页面加载后直接发起WebSocket连接+STOMP CONNECT,这时候还没有任何HTTP请求触发服务器创建HttpSession,导致令牌没有对应的会话。

解决方法:

  • 在初始化STOMP客户端前,先发送一个简单的HTTP GET请求到服务器(比如访问一个静态资源或者空接口),触发会话创建。这个请求会让服务器把XSRF-TOKEN Cookie返回给客户端,同时在服务器端创建会话并绑定令牌。

3. 检查客户端代码是否正确读取并传递令牌

以stomp.js为例,要确保正确读取Cookie中的XSRF-TOKEN,并放到CONNECT请求头里:

// 先获取Cookie中的XSRF令牌
function getCsrfToken() {
    const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);
    return match ? match[1] : null;
}

// 初始化STOMP客户端
const stompClient = new StompJs.Client({
    brokerURL: 'ws://localhost:8080/ws',
    connectHeaders: {
        'XSRF-TOKEN': getCsrfToken()
    },
    // 其他配置...
});

// 注意:先发起HTTP请求创建会话,再调用connect
fetch('/api/init-session') // 这个接口可以是空实现,只要触发会话创建
    .then(() => stompClient.connect());

4. 服务器端配置确认

Spring Security配置

确保CSRF令牌仓库配置正确,允许前端读取Cookie:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf(csrf -> csrf
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        )
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/ws/**").permitAll() // WebSocket握手端点允许匿名访问
            .anyRequest().authenticated()
        )
        // 其他配置...
    return http.build();
}

WebSocket配置

不需要额外关闭CSRF,Spring Security会自动处理STOMP帧的CSRF验证:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }
}

5. 额外排查点

  • 检查浏览器控制台的Cookie,确认XSRF-TOKEN存在且值正确传递到了CONNECT头中;
  • 确保服务器端没有禁用HttpSession(比如设置sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)会导致会话无法创建,这时候CSRF验证必然失败);
  • 如果你用的是分布式环境,要确保HttpSession能被正确共享(比如用Redis存储会话),否则不同节点可能找不到令牌对应的会话。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:07:44