使用所有方法发送预检请求

时间:2017-01-16 15:29:20

标签: javascript angular cors preflight

我的FE应用程序正在使用来自不同域的API。我知道它应该触发CORS,但据我所知它不应该为每个请求创建预检。

根据docs,我不应该有GET方法的预检请求。

 Cross-site requests are preflighted like this since they may have implications to 
 user data. In particular, a request is preflighted if:

    - It uses methods other than GET, HEAD or POST. 
Also, if POST is used to send request data with a Content-Type 
other than application/x-www-form-urlencoded, multipart/form-data, 
or text/plain, e.g. if the POST request sends an XML payload to the
server using application/xml or text/xml, then the request is preflighted.
    - It sets custom headers in the request 
(e.g. the request uses a header such as X-PINGOTHER)

但是,我发送的每个请求都有预检(OPTIONS)请求,无论是GET还是POST,我发现它很奇怪(根据文档说的那样)。

我设置了一些标题(我用withCredentials: true发送它),但我不认为它应该是问题:

  headers.append('Access-Control-Allow-Origin', FRONTEND_URL);
  headers.append('Accept', 'application/json');
  headers.append('Content-Type', 'application/json');
  headers.append('Authorization', this._generateApiKey());
  headers.append('Language', this._languageISOCode);

我错过了什么吗?

2 个答案:

答案 0 :(得分:9)

请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests

即使对于GET请求,简单请求中Content-Type标头的唯一允许值为application/x-www-form-urlencodedmultipart/form-datatext/plain。任何其他Content-Type值都会触发浏览器进行预检。

这是因为Fetch规范(定义了CORS行为)指定了它所谓的CORS-safelisted request-header,它定义为以下之一:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type,其值经解析后,具有application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 的MIME类型(忽略参数)

包含任何GET请求的任何请求(包含不是 CORS-safelisted请求标头的标头)都会触发预检。

为了让这一切变得更加清晰,我更新了the MDN documentation about CORS “simple requests”the MDN documentation about CORS preflighted requests(它实际上比上面描述的要复杂一些 - 但是上面的内容足以满足这个问题的背景。)

请注意,WebKit / Safari对AcceptAccept-LanguageContent-Language标头中允许的值设置了额外的限制。

如果其中任何一个标题具有“非标准”值,WebKit / Safari将进行预检。

至于WebKit / Safari认为这些标题的“非标准”值,除了以下WebKit错误之外,没有真正记录:

没有其他浏览器实现这些额外限制,因为它们不是规范的一部分。它们被单方面添加到WebKit,而没有与规范编辑器或其他浏览器进行任何讨论。

答案 1 :(得分:0)

跨域问题通常发生在应用程序托管在一个域上时,Web服务托管在不同的域上,我们正在尝试进行Ajax调用以获取响应。 对我们的Web服务的Ajax调用以CORS错误结束。调用的HTTP方法是OPTIONS而不是GET或POST。

解决此问题是一个方面,但我们仍需要保留安全身份验证。否则,我们最终会暴露出未经身份验证的Web服务,这是一种威胁。

if (request.getMethod().equals("OPTIONS") && request.getHeader(ORIGIN).equals(FRONTEND_URL))
{
response.setHeader("Access-Control-Allow-Origin", FRONTEND_URL);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, HEAD");
response.setHeader("Access-Control-Allow-Headers",request.getHeader("Access-Control-Request-Headers"));
}