Spring Фильтр загрузки CORS - канал предпросмотра CORS не удался

Мне нужно добавить фильтр CORS в мое веб-приложение загрузки Spring.

Я добавил сопоставления CORS, как описано в следующей документации http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html

Это моя конфигурация:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // @formatter:off   
        registry
            .addMapping("/**")
            .allowedOrigins(CrossOrigin.DEFAULT_ORIGINS)
            .allowedHeaders(CrossOrigin.DEFAULT_ALLOWED_HEADERS)
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .maxAge(3600L);
        // @formatter:on
    }

...

}

Сейчас, когда я пытаюсь получить доступ к моему API, я получаю следующую ошибку:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/api/v1.0/user. (Reason: CORS preflight channel did not succeed).

Это скриншот из консоли FF:

введите описание изображения здесь

Что я делаю неправильно и как правильно настроить заголовки CORS, чтобы избежать этой проблемы?

Ответ 1

Я исправил эту проблему, создав новый фильтр CORS:

@Component
public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token");
        response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else { 
            filterChain.doFilter(request, response);
        }
    }
}

и добавил его в конфигурацию securty:

.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class)

ОБНОВЛЕНО - более современный способ, с которого я переключился:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .cors()
        .and()

        ...
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

Ответ 2

Если бы одна и та же проблема позволяла CORS работать с остатком данных spring, это был код фильтра, который я использовал.

    /**
 * Until url{https://jira.spring.io/browse/DATAREST-573} is fixed
 * 
 * @return
 */
@Bean
public CorsFilter corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    //config.setAllowCredentials(true); // you USUALLY want this
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

Ответ 3

Для чего это стоило, для меня работало следующее комбинированное решение:

1.

@Configuration
public class CorsConfiguration {

//This can be used in combination with @CrossOrigin on the controller & method.

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("HEAD","OPTIONS")
                        .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept");
            }
        };
    }
}

2. @CrossOrigin в классе RestController. Имея @CrossOrigin, читаем аннотации @RequestMapping и методы HTTP в нем. Остальные запросы отклоняются с ошибкой CORS.

Но вам будет не повезло с вышеупомянутым решением, если вы хотите использовать spring безопасность в своем проекте.

Я использую spring версию для загрузки 1.5.4.RELEASE.

Ответ 4

Это очень просто и работает хорошо. В классе, который вы написали для конфигураций веб-безопасности, введите эту строку httpSecury.cors();


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


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

         httpSecurity.cors();     //  This enables cors

        // Your codes

    }

}


Ответ 5

Необходима правильная обработка запроса перед полетом OPTIONS, но НЕ ДОСТАТОЧНО для работы запросов на межсайтовые ресурсы.

После того, как запрос OPTIONS возвращается с удовлетворительными заголовками, все ответы на любые последующие запросы на один и тот же URL также должны иметь необходимый заголовок "Access-Control-Allow-Origin", иначе браузер проглотит их, и они выиграли даже не отображается в окне отладчика. fooobar.com/questions/404319/...

Ответ 6

Текущий рекомендуемый способ делать CORS

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("http://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);

        // Add more mappings...
    }
}

Это основано на https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-cors

Но вам также нужно убедиться, что CORS включен и CSRF отключен в вашем файле WebSecurityConfig.

Однажды у меня возникла проблема, когда все мои методы POST не работают (возвращая 403 запрещение), в то время как методы GET работают нормально, но это решается после отключения CSRF

Ответ 7

если использовать подпружиненную загрузку 2, приведенный ниже код достаточен для решения проблемы cors и предполетной проверки

@Override
    public void configure(WebSecurity web) throws Exception {
//      web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
        web.ignoring().antMatchers("/resources/**", "/index.html", "/login.html", "/partials/**", "/template/**", "/",
                "/error/**", "/h2-console", "*/h2-console/*");
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.applyPermitDefaultValues();
        config.setAllowCredentials(true);// this line is important it sends only specified domain instead of *
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }

Ответ 8

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

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS");
    }
}