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

为何WebSocket拦截器未触发?Spring STOMP认证拦截问题排查

问题分析与解决方案

首先明确:你的preSend方法没触发,核心原因是WebSocket握手阶段就返回了403 Forbidden,连接根本没建立起来,自然不会有STOMP消息进入通道触发拦截器逻辑。下面是具体排查点和修复方案:

1. 先解决403握手失败问题

403是握手阶段的错误,和STOMP消息拦截器无关,优先排查这两点:

  • 检查CustomHandshakeHandler实现
    这个Handler负责WebSocket握手时的用户认证,若beforeHandshake或determineUser方法逻辑错误,比如未正确提取认证信息、返回null用户对象,就会直接返回403。
    建议在CustomHandshakeHandler的关键方法里加日志,确认是否进入握手逻辑、认证信息是否正确获取,比如:
    @Override
    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        log.info("握手请求头: {}", request.getHeaders());
        // 从请求头提取认证token
        String token = request.getHeaders().getFirst("Authorization");
        if (token == null) {
            return null; // 返回null会导致握手失败403
        }
        // 验证token并生成用户对象
        return new UsernamePasswordAuthenticationToken("user", null, Collections.emptyList());
    }
    
  • 检查Spring Security拦截规则
    如果项目集成了Spring Security,需要确保WebSocket端点/ws被允许访问,否则Security会直接拦截握手请求返回403。在Security配置类里添加:
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/ws/**", "/ws/**/websocket").permitAll() // 放开WebSocket相关路径
            .anyRequest().authenticated();
    }
    

2. 修复STOMP拦截器触发问题

当握手成功后,STOMP的CONNECT帧发送过来时,拦截器才会触发。你的代码可以优化得更简洁:

  • 既然WebSocketConfig已经继承了ChannelInterceptorAdapter,没必要再匿名创建新的拦截器,直接注册自身即可:
@Configuration
@Slf4j
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketConfig extends ChannelInterceptorAdapter implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        // 注册当前类作为拦截器
        registration.interceptors(this);
    }

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            // 处理STOMP CONNECT帧的认证逻辑
            String token = accessor.getFirstNativeHeader("Authorization");
            if (token != null) {
                // 验证token并设置认证对象
                Authentication auth = new UsernamePasswordAuthenticationToken("user", null, Collections.emptyList());
                accessor.setUser(auth);
            }
        }
        return super.preSend(message, channel);
    }

    // 其他方法保持不变...
}

3. 额外注意点

  • 确保客户端发送STOMP CONNECT帧时携带了正确的认证信息(比如token),否则即使握手成功,STOMP阶段的认证也会失败。
  • 开启服务器日志的DEBUG级别,Spring WebSocket会输出握手和STOMP消息处理的详细日志,有助于快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:47:39