Spring boot enable Глобальная проблема поддержки CORS: работает только GET, POST, PUT и Delete не работают

Обновление: теперь, оглядываясь назад, более чем через год, я даю надежду на обновление, которое поможет кому-то еще.

Spring IO рекомендует использовать защиту CSRF для любого запроса, который может быть обработан браузером обычными пользователями. Если вы создаете только службу, которая используется не браузерными клиентами, вы, вероятно, захотите отключить защиту CSRF. Поскольку мое приложение является API и будет обрабатываться браузером, отключение CSRF не является подходом.

CSRF включен с Spring Boot по умолчанию, вам нужно добавить следующий код, чтобы добавить репозиторий CSRF и фильтр для добавления токена CSRF в ваши запросы http. (Решение приходит отсюда Неверный CSRF-токен в POST-запросе)

@Override
protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/assets/**", "/templates/**", "/custom-fonts/**", "/api/profile/**", "/h2/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .logoutSuccessUrl("/login?logout")
                .permitAll()
                .and()
            .csrf().csrfTokenRepository(csrfTokenRepository())
                .and()
            .addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class); // Register csrf filter.
               }

Часть фильтра и репозитория CsrfToken:

private Filter csrfHeaderFilter() {
    return new OncePerRequestFilter() {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response,
                                        FilterChain filterChain) throws ServletException, IOException {

            CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie == null || token != null
                        && !token.equals(cookie.getValue())) {

                    // Token is being added to the XSRF-TOKEN cookie.
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    };
}   


private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

Оригинальный вопрос, который я задал в феврале 2016 года

Я работал над поддержкой Global CORS для Spring-boot RESTful API с Spring 4.

Я следую официальному документу Spring Boot Doc (https://spring.io/guides/gs/rest-service-cors/) и добавил его в свое приложение:

public class SomeApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(SomeApiApplication.class, args);
    }


    //Enable Global CORS support for the application
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:8080")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                        .allowedHeaders("header1", "header2") //What is this for?
                        .allowCredentials(true);
            }
        };
    }
}

Я не понимаю, почему работает только GET, для остальных вызовов http я получаю сообщение об ошибке "Недопустимый запрос CORS". Я что-то пропустил в настройке? Если мои настройки не верны, GET также не должен работать. Я очень смущен.

Ответ 1

У меня была такая же проблема - GET работал. ПОСТ не. Я искал ответ в области CORS, но в конце концов обнаружил, что это связано с защитой CSRF. Чтобы решить эту проблему, я отключил защиту CSRF в конфигурации безопасности:

@Configuration @EnableWebSecurity
    public class SpringWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                **.csrf().disable()** //TODO: for production, must be reconfigured in order to disable only in specific cases. This line was added because without it, HTTP POST requests did not work. 
                .authorizeRequests()
                    .antMatchers("/api/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
        }

Убедитесь, что вы понимаете, что делаете: https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf

Ответ 2

У меня была похожая проблема, только HEAD GET и POST работали на меня. Я обнаружил, что addCorsMappings имеет значение по умолчанию для allowedMethods.

Этот код работает для меня:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("*")
                        .allowedOrigins("http://localhost:4200");
            }
        };
    }
}

Ответ 3

Попробуйте изменить метод allowedOrigins на .allowedOrigins("*"). Почтальон является расширением и работает в другом "узле".

Но убедитесь, что вы понимаете последствия: https://spring.io/understanding/CORS

Ответ 4

У меня была аналогичная проблема, и выяснилось, что @CrossOrigin на моем контроллере пришлось удалить, чтобы решить проблему. Тем не менее, чтобы выяснить, почему это вызывает "Недопустимый запрос CORS".