为何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
相关产品推荐
相关产品推荐

