未触发 CORS 检查的飞行前请求

Posted

技术标签:

【中文标题】未触发 CORS 检查的飞行前请求【英文标题】:Pre-flight Request not triggered for CORS check 【发布时间】:2019-05-23 14:46:59 【问题描述】:

据我了解,如果以下任一条件为 false(来源:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests),则浏览器会发送飞行前请求:

请求方法是 GET、HEAD 或 POST。 未设置自定义标题。 Content-Type 标头值为application/x-www-form-urlencodedmultipart/form-datatext/plain

我有一个网络应用程序,它向不同来源的服务器发送 GET 请求。由于我必须将 cookie 发送到服务器,因此属性 withCredentials 设置为 true。标头Content-Type 设置为application/json。对于这个请求,浏览器不会触发 pre-flight 请求,但它应该是因为第三个条件为 false。这背后的原因可能是什么?是否与 GET 请求的 Content-Type 标头无关紧要(因为没有请求正文)?

编辑:添加请求代码:

configObject = 
  'withCredentials': true,
  headers: 
    'Content-Type': 'application/json'
  
;

function getRequest(url, dict) 
  $http.get(url, Object.assign(, configObject)).success(function(result) 
    // on success
  ).error(function(err) 
    // on error
  );
  // return

【问题讨论】:

如果您想在这里获得其他人的见解,您需要发布您的请求代码 - 因为听起来您的实际代码没有按照问题中的描述进行操作。如果代码正在发起一个跨域请求,并且发出请求的代码实际上是将 Content-Type 标头设置为 application/json,那么这绝对会触发浏览器执行预检。总是。 @sideshowbarker 我怀疑标题是否真的被设置了。当我检查请求时(在浏览器的网络选项卡中),请求标头中不存在此标头。现在添加代码。 是的,我不确定为什么代码使用 'Object.assign(, configObject)' 作为该 .get 调用的第二个参数,而不仅仅是 'configObject',但我猜您可能只想使用“$http.get(url, configObject)”来尝试它。如果这不会导致标题按预期设置,那么我真的不知道。就个人而言,我建议只使用标准的 fetch 方法...... @sideshowbarker 这确实是问题所在。在没有请求正文的情况下,Angular 正在删除此标头。您可以将此作为答案发布吗? 【参考方案1】:

如果您的前端代码正在发起一个跨域请求,并且发出请求的代码实际上将 Content-Type 标头设置为 application/json,那么这绝对会触发浏览器进行预检。总是。

这意味着,在问题的情况下,浏览器没有被触发进行预检的原因是标头实际上没有被添加到浏览器最终发送的请求中。

但问题中描述的特殊情况是......奇怪 - 因为它试图将 Content-Type 标头添加到 GET 请求,以及问题中的 GET 请求(如几乎所有其他 GET 请求)都没有请求正文。

因此,在这种情况下,原因归结为 Angular,对于 $http 调用,会自动执行一些可以说是聪明的事情(如果出乎意料的话):在没有请求正文的情况下,它会删除 Content-Type来自请求的标头——这很有意义,因为如果没有请求正文,则不需要标头来指定其媒体类型。

请在 Angular, content type is not being sent with $http 上查看接受的答案以确认。

因此,如果出于某种原因您确实需要在没有请求正文的请求中包含 Content-Type 标头,那么解决方案是根本不使用 Angular 的 $http — 而是使用,比如说,标准 Fetch API,它允许您包含 Content-Type,即使对于缺少请求正文的请求 - 或者(如果您还需要使用 Angular 的 $http)将空的请求正文作为$http 请求(通过在请求中添加 data: '')。

【讨论】:

以上是关于未触发 CORS 检查的飞行前请求的主要内容,如果未能解决你的问题,请参考以下文章

restify cors 飞行前未连接

AWS API Gateway CORS 飞行前检查失败

(CORS) 浏览器如何知道何时进行飞行前请求

如何在浏览器的控制台中查看 CORS 飞行前 OPTIONS 请求?

在Chrome中取消了飞行前OPTIONS请求(已支持CORS)

我们应该在发送响应时关闭飞行前 Cors 请求的连接吗?