Как исправить ошибку «Access-Control-Allow-Origin» при подключении к WebSocket? - PullRequest
1 голос
/ 15 января 2020

Я работаю над проектом типа Sock JS и WebSocket, а для внешнего интерфейса я использую React и внутреннюю реализацию WebSockets, созданную весной. Но я получаю сообщение об ошибке CORS при попытке подключиться к моему WebSocket.

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;
}

И что касается метод configure в классе WebSecurity Я включил это:

@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();
}

На внешнем интерфейсе, который я подключаю к своему WebSocket с помощью метода connect:

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);
};

Я попытался задать URL-адрес метода registerStompEndpoints как 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.

1 Ответ

1 голос
/ 27 января 2020
@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. Подводя итог, я добавил .antMatchers("/ws/**").permitAll() на мой configure метод. Поэтому я разрешаю всем запросам, поступающим на мою конечную точку WebSocket, а также явно регистрировать конфигурацию CORS на всех других моих маршрутах, кроме маршрутов /ws в методе corsConfigurationSource. Надеюсь, это поможет.

...