首页 > 解决方案 > Spring Security 和 Websocket 的 CORS 问题

问题描述

我正在开发一个基于 Spring 后端的 Ionic 应用程序。我使用 JWT 身份验证实现了 Spring Security。我的应用程序将有一个聊天室,用户可以在其中私下或公开聊天。所以,我正在实现一个 WebSocket 系统,以便实时获取所有更新。

这是我的安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private UserDetailsService userDetailsService;

    private AuthenticationManager authenticationManager;

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .userDetailsService(this.userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

   // configurazione Cors per poter consumare le api restful con richieste ajax
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.setAllowedMethods(Arrays.asList("POST, PUT, GET, OPTIONS, DELETE"));
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
         httpSecurity
         .csrf().disable()
         .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
         .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
         .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().cors().and()
         .authorizeRequests()
         .antMatchers(
                 HttpMethod.GET,
                 "/",
                 "/*.html",
                 "/favicon.ico",
                 "/**/*.html",
                 "/**/*.css",
                 "/**/*.js",
                 "/image/**").permitAll()
         .antMatchers("/socket/**").permitAll()
         .antMatchers("/public/**").permitAll().and()
         .authorizeRequests().anyRequest().authenticated().and();

         httpSecurity.headers().cacheControl();
    }

    @Bean
    public AuthenticationManager customAuthenticationManager() throws Exception {
        return authenticationManager();
    }
}

这是我的 WebSocket 配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer{
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/socket")
                .setAllowedOrigins("*")
                .withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/chat")
                .enableSimpleBroker("/subscribe");
    }
}

在这种情况下,我目前面临这个错误:

从源“ http://localhost:8100 ”访问“ http://localhost:8080/SpringApp/socket/info?t=1547732425329 ”的 XMLHttpRequest已被 CORS 策略阻止:“Access-Control-”的值当请求的凭据模式为“包含”时,响应中的 Allow-Origin 标头不得为通配符“*”。XMLHttpRequest 发起的请求的凭证模式由 withCredentials 属性控制。

每个调用都在工作(我完全获得了 jwt 的授权),但 WebSocket 无法工作。

因此,我尝试在我的安全配置类中简单地删除 configure 方法中的 .cors() 。这导致我遇到一个相反的问题:

铬错误

确实,现在 WebSocket 可以完美运行,而不是每个 api 调用都给我 401。

解决此问题的正确方法是什么?谢谢

标签: springsecuritywebsocketcors

解决方案


对于复制和粘贴问题中的代码的任何人:以下行不正确:

configuration.setAllowedMethods(Arrays.asList("POST, PUT, GET, OPTIONS, DELETE"));

它应该是:

configuration.setAllowedMethods(Arrays.asList("POST", "PUT", "GET", "OPTIONS", "DELETE"));

推荐阅读