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

Spring WebSocket AccessDeniedException问题排查与配置优化

Fixing WebSocket AccessDeniedException in Spring Security

Hey there! Let's work through your WebSocket security issue step by step. First, let's recap your requirements to make sure we're aligned:

  • Anonymous access allowed: Anyone should be able to subscribe to /voting-socket/topic/proc/** without authentication
  • Restricted send access: Only logged-in users with the ADMIN role can send messages to /voting-socket/app/proc/**

Why Removing Those First Two Lines Worked (And If It's Correct)

Chances are, those first two lines in your WebSocketSecurityConfig were related to HTTP security (like @EnableWebSecurity or extending WebSecurityConfigurerAdapter), which don't belong in a WebSocket-specific security config. Mixing HTTP and WebSocket security configurations causes Spring Security to apply conflicting rules—leading to that AccessDeniedException.

Removing those lines is absolutely the right first move! But we need to make sure your WebSocketSecurityConfig is properly set up for WebSocket-specific authorization to avoid future issues.

Correct WebSocket Security Configuration

Here's how to structure your WebSocketSecurityConfig to meet your exact requirements:

@Configuration
@EnableWebSocketSecurity
public class WebSocketSecurityConfig implements SecurityWebSocketMessageBrokerConfigurer {

    @Override
    public void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
            // Allow anonymous users to subscribe to the topic endpoints
            .simpSubscribeDestMatchers("/voting-socket/topic/proc/**").permitAll()
            // Restrict send operations to authenticated ADMIN users only
            .simpDestMatchers("/voting-socket/app/proc/**").hasRole("ADMIN")
            // Require authentication for all other WebSocket messages
            .anyMessage().authenticated();
    }

    // Optional: Disable CSRF if your frontend doesn't handle it (adjust for production!)
    @Override
    public void configureWebSocketTransport(WebSocketTransportSecurityRegistry registry) {
        registry.disableCsrf();
        // Note: In production, it's better to have your frontend pass the CSRF token
        // via the `X-XSRF-TOKEN` header when establishing the WebSocket connection
    }
}

Critical Complementary Configurations

Don't forget these two key pieces to make everything work smoothly:

  1. WebSocket Message Broker Setup
    Ensure your WebSocketConfig correctly maps your destination prefixes:

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableSimpleBroker("/voting-socket/topic");
            config.setApplicationDestinationPrefixes("/voting-socket/app");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/voting-socket")
                    .withSockJS(); // Remove if you're not using SockJS
        }
    }
    
  2. HTTP Security for WebSocket Handshake
    WebSocket connections start with an HTTP handshake—so your WebSecurityConfig needs to allow access to the WebSocket endpoint:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig implements WebSecurityConfigurer {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/voting-socket/**").permitAll() // Allow handshake requests
                    .anyRequest().authenticated()
                )
                // Add your preferred authentication method (form login, OAuth2, etc.)
                .formLogin(form -> form.permitAll());
        }
    }
    

Final Checks

  • Verify that user roles are correctly assigned (make sure ADMIN users have the ROLE_ADMIN authority—Spring Security automatically prefixes roles with ROLE_ when using hasRole()).
  • If you're still seeing issues, enable debug logging for Spring Security to trace exactly where the authorization is failing:
    logging.level.org.springframework.security=DEBUG
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:06:44