복붙노트

[SPRING] 스프링 부트 CORS 필터 - CORS 프리 플라이트 채널이 성공하지 못함

SPRING

스프링 부트 CORS 필터 - CORS 프리 플라이트 채널이 성공하지 못함

스프링 부트 웹 애플리케이션에 CORS 필터를 추가해야합니다.

다음 설명서에 설명 된대로 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. ==============================

    1.새로운 CORS 필터를 만들어이 문제를 해결했습니다.

    새로운 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);
            }
        }
    }
    

    보안 구성에 추가했습니다.

    .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. ==============================

    2.CORS가 봄 데이터 휴식과 함께 작동하도록하는 것과 동일한 문제가 있었지만, 이것은 내가 사용한 필터 코드였습니다.

    CORS가 봄 데이터 휴식과 함께 작동하도록하는 것과 동일한 문제가 있었지만, 이것은 내가 사용한 필터 코드였습니다.

        /**
     * 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. ==============================

    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. RestController 클래스의 @CrossOrigin. @CrossOrigin을 사용하면 @RequestMapping 주석과 HTTP 메소드가 읽 힙니다. CORS 오류로 인해 나머지 요청이 거부됩니다.

    그러나 프로젝트에서 스프링 보안을 사용하려는 경우 위의 솔루션을 사용할 수 없습니다.

    나는 봄 부팅 버전 1.5.4를 사용하고있다. 릴리스.

  4. ==============================

    4.비행 전 OPTIONS 요청을 올바르게 처리해야하지만 크로스 사이트 리소스 요청이 제대로 작동하는 것은 아닙니다.

    비행 전 OPTIONS 요청을 올바르게 처리해야하지만 크로스 사이트 리소스 요청이 제대로 작동하는 것은 아닙니다.

    만족스러운 헤더가있는 OPTIONS 요청이 나오면 같은 URL에 대한 모든 후속 요청에 대한 응답에도 필요한 "Access-Control-Allow-Origin"헤더가 있어야합니다. 그렇지 않으면 브라우저가 해당 URL을 삼켜 버리며 심지어 디버거 창에 표시됩니다. https://stackoverflow.com/a/11951532/5649869

  5. ==============================

    5.CORS를 수행하는 현재 권장되는 방법은 다음과 같습니다.

    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를 기반으로합니다.

    그러나 WebSecurityConfig 파일에서 CORS가 활성화되어 있고 CSRF가 비활성화되어 있는지 확인해야합니다.

    한때 문제가 발생했습니다. 모든 POST 메소드가 작동하지 않습니다 (403 forbiden 반환). GET 메소드는 정상적으로 작동하지만 CSRF가 비활성화 된 후에는 해결됩니다.

  6. ==============================

    6.아래 코드 2를 사용하면 코드 문제와 프리 플라이트 문제를 해결하는 데 충분합니다.

    아래 코드 2를 사용하면 코드 문제와 프리 플라이트 문제를 해결하는 데 충분합니다.

    @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;
        }
    
  7. from https://stackoverflow.com/questions/36809528/spring-boot-cors-filter-cors-preflight-channel-did-not-succeed by cc-by-sa and MIT license