Предварительный запрос CORS не выполняется из-за стандартного заголовка

При отладке проблемы с CORS я обнаружил следующее поведение. Chrome выполняет следующий предварительный запрос OPTIONS (переписанный в CURL самим Chrome):

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 spec стандартный заголовок так что это не должно помешать выполнению запроса, верно? Почему этот заголовок вызывает такое поведение?

И как я могу настроить заголовки контроля доступа, отправленные моим сервером, чтобы запрос работал, когда выполняется с Chrome?

Кстати, я использую Chrome 36.0, а сервер использует Spring Boot, а заголовки CORS управляются Spring.

Когда запрос сделан Firefox (v47.0), поведение отличается, но с аналоговым результатом. Firefox даже не отправляет предварительный запрос, он напрямую отправляет запрос POST, который получает в ответ 403 Forbidden. Однако, если я скопирую запрос с опцией «Копировать как cURL» и повторю его из окна терминала, он выполнится успешно и отправит правильные заголовки CORS в ответе.

Любая идея?

ОбновитьFirefox отправляет предварительный запрос OPTIONS (как показано плагином Live HTTP headers), но Firebug его маскирует, поэтому поведение в обоих браузерах совершенно одинаковое. В обоих браузерах есть заголовок «Access-control-request-method» - разница, которая делает запрос неудачным.

Ответы на вопрос(5)

Решение Вопроса

е запросов в Spring для обработки трафика OPTIONS, например так:

@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 аннотация к соответствующим запросам отображений решила проблему.

 chrismarx07 сент. 2016 г., 22:10
Да, что в голову, Spring имеет процессор cors по умолчанию, но если он не настроен, он фактически прерывает обычную обработку CORS, если у вас есть его настройка в Apache. Похоже, вам нужно либо настроить CorsFilter, либо следовать советам здесь -spring.io/guides/gs/rest-service-cors
 Mike12 янв. 2017 г., 22:22
Я также нашел этот пост полезным:stackoverflow.com/questions/9521690/...  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> <загрузка при запуске> 1 </ load-on-startup> </ servlet> ...

добавив «OPTIONS» в разрешенные методы CORS в моей конфигурации Spring MVC.

@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");
    }
}

Для меня я добавил@crossorigin аннотации в каждом из вызовов контроллера 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);
}

потому что я не мог отформатировать это хорошо для ответа с наибольшим количеством голосов.

Я также нашел этот пост полезным:Как работать с HTTP-опциями в Spring MVC?

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

обальной проблемы cors при весенней загрузке

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

после этого нам нужно включить CORS на уровне безопасности Spring, поэтому для этого добавьте cors () в свой класс SecurityConfiguration, который расширяет WebSecurityConfigurerAdapter

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

        httpSecurity
                .cors()
                .and()
                .csrf().disable()
                .authorizeRequests()..

    }

Ваш ответ на вопрос