当前位置: 首页 > 知识库问答 >
问题:

由于标准标头,CORS飞行前请求失败

孔鸿远
2023-03-14

html" target="_blank">调试我遇到的CORS问题时,我发现了以下行为。Chrome发出以下选项预检请求(由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,服务器使用的是Spring Boot,CORS头由Spring管理。

当Firefox(v47.0)发出请求时,行为会有所不同,但会产生类似的结果。Firefox甚至不发送飞行前的请求,而是直接发送飞行后的请求,后者收到403禁止的响应。但是,如果我使用“copy as cURL”选项复制请求,并从终端窗口重复它,则它会成功并在响应中发送正确的CORS头。

有什么想法吗?

更新:Firefox确实发送了预检OPTIONS请求(如Live HTTP标头插件所示),但Firebug掩盖了它,因此两种浏览器中的行为完全相同。在两种浏览器中,是“Access控制请求方法”标头,这是导致请求失败的区别。

共有3个答案

祁景山
2023-03-14

我有同样的问题。我通过在Spring MVC配置中向允许的CORS方法添加“选项”来解决它。

@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");
    }
}
弘兴言
2023-03-14

我也遇到了同样的问题,并找到了在Spring boot中启用全局cors问题的解决方案

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

在此之后,我们还需要在Spring Security级别中启用CORS,因此为此,在SecurityConfiguration类中添加CORS(),扩展WebSecurity配置适配器

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

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

    }
孙承
2023-03-14

经过一番努力,我终于找到了问题所在。我在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注释添加到相应的请求映射中,解决了这个问题。

 类似资料:
  • 我遇到了以下问题:在起飞前的OPTIONS请求成功后,随后的POST请求失败。这有点违反直觉,因为一旦选项成功,随后的请求应该被接受。 流程如下: 响应头 后请求 发布响应(通知是返回200,我实际上看到了结果内容,所以后端可以请求) 错误消息 请求的资源上不存在“Access Control Allow Origin”标头。起源'http://localhost:4200因此,不允许访问。

  • 我不清楚CORS头(Access-Control-Allow-Origin等)是否应该只出现在飞行前请求(OPTIONS方法)中,还是也出现在资源的头中(我试图使用XHR发布)

  • 我让这个项目在Angular 8中运行,并使用飞行前和实际的api调用api。而且我们在它的网络安全上有一个问题,因为飞行前的选项没有标题严格的传输安全性:max age=31536000;includeSubDomains,而实际的GET api有一个。 您是否知道如何以及在哪里添加严格运输安全:max-age=31536000;包括预飞行和实际请求下的子域,以便两个请求将具有相同的标头?

  • 问题内容: 我有一个简单的PHP脚本,正在尝试跨域CORS请求: 但是我仍然得到错误: 请求标头字段不允许 我有什么想念的吗? 问题答案: 不允许作为可接受的值,请参阅此处的Mozilla文档。 您应该发送可接受的标头(而不是如星号所示)而不是星号。

  • 所以这里的是一个类似JWT的标记。 在我的Angular代码中,我只需将令牌添加为,如下所示: 请注意,我的身份验证/注册路由工作正常,我只是在将标头传输到Spring服务器时遇到了困难。 谢谢,

  • 我使用AJAX请求通过POST将数据发送到另一个域。因为我的内容类型不是标准的(它是JSON格式),所以需要一个飞行前请求。(使用请求方法:选项) 如维基百科跨域XHR调用图表中所述 我想知道这是否很费时,因为浏览器将必须到达服务器两次或不?也许这取决于每个浏览器的行为? 通过使用内容类型“纯文本”来避免飞行前请求,我是否获得了一些时间?