복붙노트

[SPRING] CORS 프리 플라이트 요청이 표준 헤더로 인해 실패합니다.

SPRING

CORS 프리 플라이트 요청이 표준 헤더로 인해 실패합니다.

CORS 문제를 디버깅하는 동안 다음과 같은 문제가 발견되었습니다. Chrome은 다음 OPTIONS 프리 플라이트 요청을합니다 (Chrome 자체에서 CURL로 다시 작성).

curl -v 'https://www.example.com/api/v1/users' -X OPTIONS -H 'Access-Control-Request-Method: POST' -H 'Origin: http://example.com' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Accept-Language: es-ES,es;q=0.8,en;q=0.6' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://example.com/users/new' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: accept, x-api-key, content-type'

다음과 같은 경우 서버에서이 요청에 대한 응답 :

< HTTP/1.1 403 Forbidden
< Date: Thu, 21 Jul 2016 14:16:56 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: SAMEORIGIN
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
< Content-Length: 20
< Keep-Alive: timeout=5, max=100
< Connection: Keep-Alive

'잘못된 CORS 요청'응답의 본문입니다. 헤더 'Access-Control-Request-Method'(그리고 단지 헤더)를 제거하는 요청을 반복하면 OPTIONS 요청은 다음 응답으로 성공합니다 :

< HTTP/1.1 200 OK
< Date: Thu, 21 Jul 2016 14:21:27 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: SAMEORIGIN 
< Access-Control-Allow-Headers: origin, content-type, accept, x-requested-with, x-api-key
< Access-Control-Max-Age: 60
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Allow-Origin: *
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
< Content-Length: 0
< Keep-Alive: timeout=5, max=100
< Connection: Keep-Alive

그러나 문제의 헤더는 CORS 사양 표준 헤더이므로 요청이 성공하지 못하도록해야합니다. 이 헤더가 왜 그런 행동을 일으키는가?

그리고 내 서버에서 보낸 액세스 제어 헤더를 수정하여 Chrome으로 요청을 작동하게하려면 어떻게해야합니까?

그런데 Chrome 36.0을 사용하고 있으며 서버는 스프링 부트를 사용하고 CORS 헤더는 스프링에서 관리합니다.

Firefox (v47.0)에서 요청을하면 동작은 다르지만 아날로그 결과가 표시됩니다. 파이어 폭스는 프리 플라이트 요청을 보내지도 않고 POST 요청을 직접 보낸다.이 요청은 403 Forbidden으로 응답한다. 그러나 'cURL로 복사'옵션을 사용하여 요청을 복사 한 다음 터미널 창에서이를 반복하면 응답에 올바른 CORS 헤더가 성공하고 전송됩니다.

어떤 생각?

업데이트 : 파이어 폭스는 라이브 HTTP 헤더 플러그인에 표시된 것처럼 프리 플라이트 OPTIONS 요청을 보내지 만 파이어 버그는이를 마스크하므로 두 브라우저의 동작이 완전히 동일합니다. 두 브라우저 모두에서 'Access-control-request-method'헤더가 요청을 실패하게 만듭니다.

해결법

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

    1.많은 어려움 끝에 마침내 문제를 발견했습니다. OPTIONS 트래픽을 처리하기 위해 Spring에서 요청 매핑을 다음과 같이 설정했다 :

    많은 어려움 끝에 마침내 문제를 발견했습니다. OPTIONS 트래픽을 처리하기 위해 Spring에서 요청 매핑을 다음과 같이 설정했다 :

    @RequestMapping(value= "/api/**", method=RequestMethod.OPTIONS)
    public void corsHeaders(HttpServletResponse response) {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with");
        response.addHeader("Access-Control-Max-Age", "3600");
    }
    

    나는 기본적으로 Spring이 기본 CORS 프로세서를 사용한다는 것을 알지 못했고 요청 매핑을 방해하고있는 것으로 보인다. 요청 매핑을 삭제하고 @CrossOrigin 주석을 적절한 요청 매핑에 추가하면 문제가 해결됩니다.

  2. ==============================

    2.나는 또한 같은 문제에 직면하고 봄 부팅에서 글로벌 cors 문제를 활성화하기위한 해결책을 찾는다.

    나는 또한 같은 문제에 직면하고 봄 부팅에서 글로벌 cors 문제를 활성화하기위한 해결책을 찾는다.

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                    .allowedHeaders("*");
        }
    }
    

    이 후에도 봄 보안 수준에서 CORS를 사용할 수 있어야하므로 SecurityConfiguration 클래스에 cors ()를 추가합니다. 범위는 WebSecurityConfigurerAdapter입니다.

     @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {
    
            httpSecurity
                    .cors()
                    .and()
                    .csrf().disable()
                    .authorizeRequests()..
    
        }
    
  3. ==============================

    3.나는 같은 문제가 있었다. 내 봄 MVC 구성에서 허용 된 CORS 메서드에 'OPTIONS'을 추가하여 해결했습니다.

    나는 같은 문제가 있었다. 내 봄 MVC 구성에서 허용 된 CORS 메서드에 'OPTIONS'을 추가하여 해결했습니다.

    @Configuration
    @EnableWebMvc
    @ComponentScan
    public class RestApiServletConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            super.addCorsMappings(registry);
            registry.addMapping("/**")
                    .allowedOrigins("http://localhost:3000", "http://localhost:8080")
                    .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS");
        }
    }
    
  4. ==============================

    4.내가 최고 투표 응답을 위해 그것을 형식화 할 수 없기 때문에 이것을 답으로 추가했습니다.

    내가 최고 투표 응답을 위해 그것을 형식화 할 수 없기 때문에 이것을 답으로 추가했습니다.

    나는이 글이 도움이된다는 것을 발견했다. 스프링 MVC로 HTTP 옵션을 처리하는 방법은?

    DispatchServlet은 옵션 요청을 전달하도록 구성되어야하며 그렇지 않으면 매핑 된 요청에 도달하지 않습니다.

    ...
      <servlet>
        <servlet-name>yourServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>dispatchOptionsRequest</param-name>
          <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
    ...
    
  5. ==============================

    5.나를 위해 @crossorigin annotation을 각 컨트롤러 API 호출에 추가했습니다.

    나를 위해 @crossorigin annotation을 각 컨트롤러 API 호출에 추가했습니다.

    @CrossOrigin
    @PostMapping(path = "/getListOfIndividuals", produces = { "application/json" }, consumes = { "application/json" })
    public ResponseEntity<String> test(@RequestBody String viewIndividualModel)
            throws Exception {
        String individualDetails = globalService.getIndividualDetails(viewIndividualModel);
    
    
        finalString = discSpecAssmentService.getViewFormForDisciplineEvaluation( viewIndividualModel);
    
        return new ResponseEntity<String>(finalString, HttpStatus.OK);
    }
    
  6. from https://stackoverflow.com/questions/38507370/cors-preflight-request-fails-due-to-a-standard-header by cc-by-sa and MIT license