由于标准标题,CORS预检请求失败

By simon at 2018-02-28 • 0人收藏 • 54人看过

在调试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请求'。如果我重复请求 删除标题'访问控制请求 - 方法“(只有那个头) 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
但是,他得罪了ader是[CORS规格标准 报头(https://developer.mozilla.org/en-US/docs/Web/HTTP/AccesscontrolCORS #访问控制,热曲est-Method),所以它不应该阻止请求 成功,对吗?为什么这个头引起这样的行为? 怎么会我调整了由我的服务器发送的访问控制标题以使其成为可能 请求使用Chrome进行工作? 顺便说一下,我正在使用Chro我36.0,并且服务器正在使用Spring Boot, CORS头文件由Spring管理。 当请求由Firefox进行时(v47.0)行为是不同的,但是 与模拟结果。 Firefox甚至不会发送预检请求 直接的结束POST请求,其中收到403 Forbidden作为响应。 但是,如果我将该请求复制为“Copy as cURL”选项,并重复它 从终端窗口中,它成功并发送正确的CORS标头 响应。 任何想法? 更新:Ffirefox确实发送预检选项请求(如图所示) Live HTTP头插件),但Firebug掩盖它,所以行为两者都有 浏览器完全一样。在这两种浏览器中都是'Access-control-request- 方法'标题的差异,使请求失败。

5 个回复 | 最后更新于 2018-02-28
2018-02-28   #1

经过很多苦苦挣扎,我终于找到了问题。我配置了一个请求 在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 处理器(http://docs.spring.io/spring/docs/curreNT / javadoc- api / org / springframework / web / cors / DefaultCorsProcessor.html),看起来它 干扰了我的请求映射。删除我的请求映射和 添加[@CrossOrigin](http://docs.spring.io/spring/docs/4.2.1.RELEASE / Javadoc的API /组织/ SPRingframework /网络/结合/注解/ CrossOrigin.html) 注释到适当的请求映射解决了这个问题。

2018-02-28   #2

经过很多苦苦挣扎,我终于找到了问题。我配置了一个请求 在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 处理器(http://docs.spring.io/spring/docs/curreNT / javadoc- api / org / springframework / web / cors / DefaultCorsProcessor.html),看起来它 干扰了我的请求映射。删除我的请求映射和 添加[@CrossOrigin](http://docs.spring.io/spring/docs/4.2.1.RELEASE / Javadoc的API /组织/ SPRingframework /网络/结合/注解/ CrossOrigin.html) 注释到适当的请求映射解决了这个问题。

2018-02-28   #3

我添加了这个答案,因为我无法对顶级投票进行格式化 回答。 我发现这篇文章也很有帮助:[如何用Spring处理HTTP OPTIONS MVC?](https://stackoverflow.com/questions/9521690/how-to-handle-http-options- 与弹簧-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>
...

2018-02-28   #4

我遇到过同样的问题。我已通过向允许的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");
    }
}

2018-02-28   #5

我也面临同样的问题,并寻找解决方案来解决全球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类的extent中添加cors() WebSecurityConfigurerAdapter
 @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

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

    }

登录后方可回帖

Loading...