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

Spring Boot 3.0.6自定义AuthorizationChannelInterceptor覆盖失败求助

Spring Boot 3.0.6 自定义WebSocket安全拦截器失败问题解决

核心问题原因

Spring Security 6.x(对应Spring Boot 3.x)中,WebSocket安全默认由AuthorizationChannelInterceptor处理,该拦截器优先级高于自定义拦截器,且若未正确将HTTP握手阶段的认证信息传递到WebSocket消息通道,就会导致后续处理时Authentication始终处于匿名状态,触发AccessDeniedException。

常见配置错误及修正方案

1. 未正确替换默认拦截器

Spring Boot 3.x中不能直接添加自定义拦截器覆盖默认逻辑,需在WebSocketMessageBrokerConfigurer中先移除默认拦截器,再将自定义拦截器设为最高优先级:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    private final CustomAuthChannelInterceptor customAuthChannelInterceptor;

    public WebSocketConfig(CustomAuthChannelInterceptor customAuthChannelInterceptor) {
        this.customAuthChannelInterceptor = customAuthChannelInterceptor;
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        // 移除默认授权拦截器,添加自定义拦截器并设为最高优先级
        registration.setInterceptors(customAuthChannelInterceptor)
                    .order(Ordered.HIGHEST_PRECEDENCE);
    }

    // 其他WebSocket配置(如消息代理、端点映射)...
}

2. 自定义拦截器未正确处理认证信息

自定义拦截器需在WebSocket CONNECT阶段从握手请求中提取认证凭证(如Token),生成Authentication并设置到上下文,确保后续流程能获取到认证信息:

@Component
public class CustomAuthChannelInterceptor implements ChannelInterceptor {

    private final AuthenticationManager authenticationManager;

    public CustomAuthChannelInterceptor(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            // 从请求头提取Token(示例为Bearer Token)
            String token = accessor.getFirstNativeHeader("Authorization");
            if (token != null && token.startsWith("Bearer ")) {
                token = token.substring(7);
                // 自定义Token认证逻辑,生成Authentication
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(null, token);
                Authentication authentication = authenticationManager.authenticate(authRequest);
                // 将认证信息存入上下文及StompHeaderAccessor
                SecurityContextHolder.getContext().setAuthentication(authentication);
                accessor.setUser(authentication);
            }
        }
        return message;
    }
}

3. SecurityConfig未放行WebSocket握手端点

需确保Spring Security配置中放行WebSocket握手端点,避免HTTP握手阶段被拦截导致认证信息丢失:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                // 放行WebSocket握手端点(根据实际路径调整)
                .requestMatchers("/ws/**").permitAll()
                .anyRequest().authenticated()
            )
            // 若使用Token认证,需禁用CSRF(WebSocket握手一般不依赖Cookie+CSRF)
            .csrf(csrf -> csrf.disable())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        return http.build();
    }

    // 自定义AuthenticationManager、UserDetailsService等Bean...
}

4. 未配置SecurityContext线程传播

WebSocket消息线程默认不会继承HTTP请求的SecurityContext,需设置线程上下文继承策略,确保认证信息能传递到WebSocket处理线程:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 设置SecurityContext可被子线程继承
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
        SpringApplication.run(Application.class, args);
    }
}

关键注意事项

  • 必须在CONNECT阶段完成认证,SUBSCRIBE等后续命令会依赖此时设置的Authentication;
  • 若未移除默认AuthorizationChannelInterceptor,它会优先执行,此时认证信息尚未设置,必然触发权限异常;
  • 确保握手请求正确携带认证凭证(如Token),且自定义拦截器的认证逻辑与系统现有认证机制一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:17:27