连接到 WebSocket 时如何修复“Access-Control-Allow-Origin”错误?

Posted

技术标签:

【中文标题】连接到 WebSocket 时如何修复“Access-Control-Allow-Origin”错误?【英文标题】:How to fix the 'Access-Control-Allow-Origin' error when connecting to a WebSocket? 【发布时间】:2020-01-15 14:16:49 【问题描述】:

我正在开发一个 SockJS 和 WebSocket 类型的项目,我在前端使用 React,在后端使用 Spring 的 WebSockets 实现。但是当我尝试连接到我的 WebSocket 时遇到了 CORS 错误。

Access to XMLHttpRequest at 'http://localhost:8080/ws/info?t=1579096675068' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

在 Java 项目中,我已经包含了这个 CORS 配置:

@Bean
CorsConfigurationSource corsConfigurationSource() 
     final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
     final CorsConfiguration configuration = new CorsConfiguration();
     configuration.applyPermitDefaultValues();
     configuration.setExposedHeaders(Arrays.asList("Authorization"));
     configuration.addAllowedOrigin("*");
     configuration.addAllowedMethod("*");
     configuration.addAllowedHeader("*");
     source.registerCorsConfiguration("/**", configuration);
     return source;

至于WebSecurity 类上的configure 方法,我已经包含了这个:

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors().and().csrf().disable().authorizeRequests()
             .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
             .anyRequest().authenticated()
             .and()
             .addFilter(new JWTAuthenticationFilter(authenticationManager()))
             .addFilter(new JWTAuthorizationFilter(authenticationManager()))
             .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);

我像这样添加我的套接字端点:

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) 
    registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();

在前端,我使用 connect 方法连接到我的 WebSocket:

connect = () => 
  const Stomp = require("stompjs");
  let SockJS = require("sockjs-client");
  SockJS = new SockJS("http://localhost:8080/ws");
  stompClient = Stomp.over(SockJS);
  stompClient.connect(, this.onConnected, this.onError);
;

我尝试将registerStompEndpoints 方法上的URL 明确设置为http://localhost:3000,但没有效果。还在前端我的package.json 上添加了一个代理到http://localhost:8080/,但它仍然给出了同样的错误。我需要在我的corsConfigurationSource 上做些什么才能让它正常工作吗?

更新

当我执行以下 configure 方法时,它解决了 WebSocket 问题,因为它可以连接到它,但我无法访问我的应用程序的其他路由,因为它给出了另一个错误。

protected void configure(HttpSecurity http) throws Exception 
     http.authorizeRequests()
             .antMatchers("/ws").permitAll()
             .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
             .and()
             .addFilter(new JWTAuthenticationFilter(authenticationManager()))
             .addFilter(new JWTAuthorizationFilter(authenticationManager()))
     .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().csrf().disable();

另一个错误:

Access to XMLHttpRequest at 'http://localhost:8080/auth/me' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

【问题讨论】:

我有一个像你一样的应用程序并且运行良好。已经实现了cors 这样的***.com/a/58127178/7458887。 【参考方案1】:
@Override
    protected void configure(HttpSecurity http) throws Exception 
        http.cors().and()
              .authorizeRequests()
              .antMatchers("/ws/**").permitAll()
              .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
              .anyRequest().authenticated()
              .and()
              .addFilter(new JWTAuthenticationFilter(authenticationManager()))
              .addFilter(new JWTAuthorizationFilter(authenticationManager()))
              .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
              .and().csrf().disable();


@Bean
CorsConfigurationSource corsConfigurationSource() 

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setExposedHeaders(Arrays.asList("Authorization"));
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.applyPermitDefaultValues();
        source.registerCorsConfiguration("/api/**", configuration);
        source.registerCorsConfiguration("/auth/*", configuration);
        source.registerCorsConfiguration("/login", configuration);
        return source;

我最终将它用作我的 WebSecurity。总而言之,我在configure 方法中添加了.antMatchers("/ws/**").permitAll()。因此,我允许所有请求到达我的 WebSocket 端点,并在我的所有其他路由上显式注册 CORS 配置,除了 corsConfigurationSource 方法上的 /ws 路由。希望这会有所帮助。

【讨论】:

非常感谢。我花了几个小时寻找这个。

以上是关于连接到 WebSocket 时如何修复“Access-Control-Allow-Origin”错误?的主要内容,如果未能解决你的问题,请参考以下文章

当python中的连接失败时如何重新连接到websocket

如何在连接到节点上的 websocket 服务器时传递消息

OkHttp Websockets - 连接到 websocket 时添加一个主体

如何使用 websocket 安全地将我的 cli 应用程序连接到网站

当我尝试连接到Mysql时,如何在检测到JSONException时修复错误?

如何修复“连接到 localhost:6379 的错误 111。当我启动 rq-worker 时连接被拒绝?