복붙노트

[SPRING] OPTIONS / DELETE에 대해 봄 부팅 데이터 Rest + CORS가 올바르게 설정되지 않음

SPRING

OPTIONS / DELETE에 대해 봄 부팅 데이터 Rest + CORS가 올바르게 설정되지 않음

내가 일할 수없는 극히 간단한 예가있다.

내 도메인과 데이터베이스를 모델링합니다.

public interface MyTestRepository extends CrudRepository<MyTest, Integer> {
}

나는 그것을 테스트하기 위해 http://resttesttest.com/을 사용했다. GET 메서드의 경우 문제없이 JSON REST 정보를 반환합니다.

끝점 http : // localhost : 8080 / mytest / 1을 질의 할 수 있고 데이터베이스에서 id = 1에 대한 정보를 얻는다.

그러나 DELETE 옵션을 사용하려고하면 문제가 발생합니다. http : // localhost : 8080 / mytest / 1에서 DELETE를 실행하면

나는 처음에 다음을 시도했지만 스프링 - 데이터 - 레스트를 사용하기 때문에 사용할 수 없다는 것을 알았다. https://jira.spring.io/browse/DATAREST-573

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("*")
        .allowedHeaders("*")
        .allowCredentials(true).maxAge(3600);
}

나는 주위를 봤 거든 이것을 발견했다.

Spring Boot + Spring Security 애플리케이션에서 CORS를 구성하는 방법은 무엇입니까?

그래서 나는 덧붙였다.

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

나는 또한이 스레드를 발견했다.

봄 데이터 나머지 및 Cors

그리고 다음 코드를 시도했지만 운이 없다.

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    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);
    final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

모든 CORS가 현명하게 통과해야하는 테스트를 위해 모든 캐치를 추가했지만 "*"이 있더라도 여전히 No 'Access-Control-Allow-Origin'을 계속 유지합니다.

이 시점에서 프리 플라이트 요청이 액세스 제어 검사를 통과하지 못하는 이유에 대해 내가 모르는 것을 알지 못합니다.

curl은 삭제를 발행해도 문제가 없습니다.

편집하다:

정확한 해결책을 찾는 것을 끝내었다. 내가 가지고있는 것과이 방법의 차이점에 대해서는 잘 모르겠지만 이것이 효과가있는 것 같습니다.

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Note this is a very simple CORS filter that is wide open.
 * This would need to be locked down.
 * Source: https://stackoverflow.com/questions/39565438/no-access-control-allow-origin-error-with-spring-restful-hosted-in-pivotal-web
 */
@Component
public class CORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}

}

해결법

  1. ==============================

    1.이것은 내가 모든 CORS 서블릿 필터 허가로 사용하는 것입니다 :

    이것은 내가 모든 CORS 서블릿 필터 허가로 사용하는 것입니다 :

    public class PermissiveCORSFilter implements Filter {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(PermissiveCORSFilter.class);
        private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9 ,-_]*$");
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
    
            String origin;
            String credentialFlag;
            if (request.getHeader("Origin") == null) {
                origin = "*";
                credentialFlag = "false";
             } else {
                origin = request.getHeader("Origin");
                credentialFlag = "true";
             }
    
            // need to do origin.toString() to avoid findbugs error about response splitting        
            response.addHeader("Access-Control-Allow-Origin", origin.toString());
            response.setHeader("Access-Control-Allow-Credentials", credentialFlag);
            if ("OPTIONS".equals(request.getMethod())) {
                LOGGER.info("Received OPTIONS request from origin:" + request.getHeader("Origin"));
                response.setHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS,PUT,DELETE");
                response.setHeader("Access-Control-Max-Age", "3600");
                String headers = StringUtils.trimToEmpty(request.getHeader("Access-Control-Request-Headers"));
                if (!PATTERN.matcher(headers).matches()) {
                    throw new ServletException("Invalid value provided for 'Access-Control-Request-Headers' header");
                }
                response.setHeader("Access-Control-Allow-Headers", headers); // allow any headers
            }
            chain.doFilter(req, res);
        }
    
        @Override
        public void init(FilterConfig filterConfig) {
            // Do nothing
        }
    
        @Override
        public void destroy() {
            // Do nothing
        }
    
  2. ==============================

    2.Spring Data Rest 기반 어플리케이션에서 다음과 같은 설정이 가능합니다. 중요한 점은 보안 필터 체인이 시작되기 전에 필터가 실행되도록 등록된다는 것입니다.

    Spring Data Rest 기반 어플리케이션에서 다음과 같은 설정이 가능합니다. 중요한 점은 보안 필터 체인이 시작되기 전에 필터가 실행되도록 등록된다는 것입니다.

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter
    {
      @Override
      public void configure(HttpSecurity http) throws Exception
      {
        http.addFilterBefore(corsFilter(), ChannelProcessingFilter.class);
      }
    
      @Bean
      protected Filter corsFilter()
      {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        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");
        config.addExposedHeader("Location");
    
        source.registerCorsConfiguration("/**", config);
    
        return new CorsFilter(source);
      }
    }
    
  3. from https://stackoverflow.com/questions/40009719/spring-boot-data-rest-cors-not-being-enabled-properly-for-options-delete by cc-by-sa and MIT license