Chrome 忽略 Access-Control-Allow-Origin 标头,并在调用 AWS Lambda 时因预检错误导致 CORS 失败

IT技术 reactjs ajax google-chrome aws-lambda cors
2021-05-23 01:39:45

我正在构建一个 ReactJS 前端,它必须使用 JS fetch 从 AWS Lambdas 收集一些数据。无论我应用什么 CORS 技术,我都无法让它发挥作用。我在这里查看了其他答案无济于事。

我肯定将Access-Control-Allow-Origin"*"在我的响应值(验证了这一点使用邮递员叫端点)。此外,Chrome 抱怨预检Response to preflight request doesn't pass access control check,但OPTIONSchrome 没有真正触发预检请求(方法),我所看到的只是GET我试图首先制作的,这真的很令人困惑。

我错过了什么?当没有提出 OPTIONS 预检请求时,为什么 chrome 会抱怨预检?为什么在我的回复中添加Access-Control-Allow-Originwith"*"是不够的?

谢谢!

1个回答

TL; DR:一个预检要求发生,它只是没有显示在铬(还有一种方法,使他们出现)。此外,例如,如果您将自定义标头用于授权令牌,则需要进行调整。

概括

好吧,在研究了一天并检查了其他几个答案之后,我发布了这个,因为没有一个完全适合我的问题,希望它能帮助其他人解决这个问题。首先,我将总结错误中涉及的几个部分,然后总结如何修复它,而不像许多帖子建议的那样求助于任何“hackish”解决方案,例如使用 chrome 扩展绕过 CORS,或使用任何 3rd 方服务。我的设置如下所示:

  • ReactJS 前端,尝试使用 fetch javascript 方法发出 GET 请求,运行在http://localhost:3000 上进行开发
  • AWS Lambda 后端,它使用 JSON 有效负载(用 Python 编码,不重要但无论如何)回答 GET。此 lambda 正在Access-Control-Allow-Origin:"*"为其响应添加标头。
  • 上面的 AWS Lambda 是 AWS 所谓的“Authorizer”的背后,这是一个在您的 lambda 之前运行的函数,用于检查您想要使用的任何授权标头来保护对您的 API 的访问。这很重要,我们稍后会看到,因为由于 AWS 内部工作上的一些废话,有时您不能使用标准的 HTTP Authorization 标头,并且默认使用 AuthorizationToken 正如他们在文档和示例中建议的那样(并且并不总是更改它有效,有很多用户在他们的论坛中报告了这一点)。我们将对此进行记录以备后用。
  • 两种 API 方法(实际 API 及其授权方)都使用 AWS API Gateway 在 Internet 上路由和发布,简而言之,这是一种将 lambda 与公共 URL 配对以从其他地方调用它的方法。
  • 用作浏览器的谷歌浏览器(使用其开发者工具来监控事物)

错误

当试图调用lambda,铬块与此错误显示在控制台上的GET请求:Response to preflight request doesn't pass access control check我的 lambda 已经用正确的Access-Control-Allow-Origin标题回答了,有什么问题吗?此外,OPTIONS无论如何都没有提出预检请求,所以这很令人困惑。

一些调试

AWS Lambda 很棒,但他们的调试工具不像我想要的那么流畅,所以我用本地 expressjs 服务器替换了 lambda,只实现了两种方法:GET /foo 和 OPTIONS /foo。令我惊讶的是,当我从我的 ReactJS 前端获取 /foo 时,它确实首先调用了 OPTIONS /foo(我通过将日志添加到我的端点等来确认这一点,您也可以在 lambdas 中执行此操作,但并不那么容易)。

实际发生了什么

“预检”请求是一个 OPTIONS 请求,用于验证执行以下 GET 时实际允许的内容,但 Chrome 中的网络选项卡没有显示任何实际发生的 OPTIONS 请求(我记得它们曾经出现在这里)。好吧,他们在某个时候改变了它,现在默认情况下它们是隐藏的。如果你希望他们再次显示(作为一个开发者,我这样做),你可以通过改变重新启用该out-of-blink-cors标志disabled作为解释在这里

更改此标志后,现在 OPTIONS 请求确实显示在网络选项卡上。从那里我可以制作 OPTIONS 响应,以便之后启用所需的 GET。使用凭据和其他情况时还有其他注意事项(我发现Mozilla 的这篇文章对此很有帮助),但简而言之,我的 OPTIONS 响应标头如下所示:

Access-Control-Allow-Origin: "http://localhost:3000"
Access-Control-Allow-Methods: "GET, POST, OPTIONS"
Access-Control-Allow-Headers: "authorizationToken"

(最后一个 ,Access-Control-Allow-Headers在处理 AWS Lambdas Authorizers 时发挥作用。如果您使用该自定义标头发送您的令牌,则需要在此处允许它)。

在使 CORS 在本地工作后,为了解决我的 lambdas 问题,我做了两件事:

  1. 您需要 API 网关才能响应 OPTIONS 请求。有多种方法可以实现这一点,从编写您自己的 lambda 来回答它,到让 AWS 为您模拟响应。更多信息在这里
  2. 您需要确保您的 GET lambda 添加Access-Control-Allow-Origin标头,指向您的 OPTIONS 响应所做的相同值(在我的情况下,http://localhost:3000)。

之后,一切都按预期进行。

最后的笔记

我写这个答案是因为我发现我发现的任何问题实际上都没有涵盖“React-CORS-AWS-Authorization”的结合。

此外,在 chrome 上使用 localhost 进行开发可能会出现许多问题,导致建议使用像 lvh.me 这样的外部服务,但事实并非如此,并且一些答案误导性地将这个 CORS 问题与此相关联。此外,一些答案建议使用一些 chrome 扩展完全禁用 CORS 检查,这确实是一个糟糕的安全建议。

最后,我发现制作一个简单的 expressJS 服务器来调试服务器端事物的想法对于理解正在发生的事情非常有帮助,因为有时你根本无法访问另一端发生的事情,所以也许这个建议可以帮助人们缩短处理这样的事情的时间。