API 网关 CORS 问题

Posted

技术标签:

【中文标题】API 网关 CORS 问题【英文标题】:API Gateway CORS Issue 【发布时间】:2016-05-18 14:09:31 【问题描述】:

所以我通过 AWS Gateway 提供的基本设置启用了 CORS。但是对于这个 API,我需要允许所有请求的控制源并允许凭据。

这是它的样子

您可能已经猜到的问题是 CORS 不允许此设置,您不能为 Origin 使用通配符,并且凭据为 true。通常,解决此问题的方法是获取请求域并将其添加到 Origin Header 中。这或多或少是我想做的。但我不知道如何获取该信息并将其添加为映射值。 API Gateway 将这些信息存储在哪里?我如何获取这些信息?

更新: 我必须将 HTTP 标头主机传递给我应该在前面提到的 Lambda 函数,我已尝试实现下面的答案,但我无法使用提供的说明访问标头以将其传递给 Lambda 函数。非常感谢您提供更多帮助。

【问题讨论】:

感谢您的反馈。本周我们刚刚添加了对传递“Host”和“User-Agent”标头的支持。您可以尝试再次访问这些标头吗?请让我知道它是否对您有用。谢谢,Jurgen - API 网关 【参考方案1】:

来自 API Gateway 的 Jurgen。 感谢您报告此问题。目前没有简单的方法可以通过控制台中的“启用 CORS”功能进行设置。不过,我们正在研究它以改善此用例的用户体验。

作为一种潜在的解决方法,您可以将 Origin 标头从客户端传递到您的后端,并在那里解析/创建 Access-Control-Allow-Origin 标头的值。然后将集成响应中的 Header 从 'integration.response.header.Access-Control-Allow-Origin' 映射到 Access-Control-Allow-Origin 并将其返回给客户端。

希望这会有所帮助。

最好, 于尔根

【讨论】:

谢谢,我想我可以将值与我的其余响应一起传递并在那里处理它。 跟进问题。我将如何通过 Origin Header,即其中包含什么 API 变量。 需要在方法请求中指定Origin头。在集成请求中,您可以通过 method.request.header.Origin 访问它。对于集成响应,您将使用 integration.response.header.XYZ。您可以在这里查看如何设置方法请求和响应标头:docs.aws.amazon.com/apigateway/latest/developerguide/… 我该死的想把它弄好。我需要为我的 xhr 请求设置 widthCredentials 以发送 Cookie 标头,但我无法使用 api 网关进行设置,因为我无法将 Access-Control-Allow-Origin 设置为 *。我该如何解决这个问题? 今天这也让我感到震惊。事实证明,如果您想使用自己的 CORS 验证而不是 AWS 的“允许一切带有假装检查”的默认设置,那么 Jurgen 的解决方法仍然是必要的。只需将“Origin”添加到请求传递的标头中,并将“Access-Control-Allow-Origin”添加到响应传递的标头中。(以及您的情况下需要的其他标头)【参考方案2】:

好的,经过数小时的研究并在互联网上找到一些信息后,我有了一个解决方案,希望它对其他人有用。

要传递不是 AWS API Gateway 提供的默认值的 HTTP 标头,然后通过 Lambda 函数访问该数据并在响应标头中返回该数据,请按照以下步骤操作

    在“方法请求”中,转到“HTTP 请求标头”并添加您想要捕获的标头。 IE。如果我们想获取 API url 的主机值,您可以在此处输入“主机”。如果您想获取调用者的网站主机,请使用“Origin”

    在“集成请求”中,如果“应用程序/json”不存在,则转到映射模板并创建一个新模板,如果它只是更新它。

这是重要的部分,传递您在步骤 1 中设置的标头值。为此,请在模板框中编写类似于以下内容的内容。


   "origin" : "$input.params().header.Origin",
   "host" : "$input.params().header.Host"

你也可以传入你在同一个 JSON 中定义的任何 url 参数。

    从 Lambda 访问数据,如果使用 Node 作为 Lambda 后端代码,集成请求会将信息传递到“Event”参数中。要检索任何标头的值,只需在您的处理程序中使用以下内容。

    event.origin;
    

    将您的响应从 Lambda 发送回 API Gateway 时,最好将响应格式化为 JSON。类似的东西。

     
       "origin" : event.origin,
       "host" : event.host,
       "nonHeaderOutput" : "Hello World"
    
    

    在“Integration Response”中转到“Header Mappings”,如果您需要的标头未列出,您可以在“Method Response”中添加它,然后它会出现在这里。对于这个例子,我使用“Access-Control-Allow-Origin”并将映射值编辑为integration.response.body.origin

    现在转到“映射模板并选择要使用的内容类型,然后通过将其添加到模板框来编辑模板以访问非标题响应

    $input.path("$.nonHeaderOutput")
    

现在发送到 API 的标头可以在您的方法响应中使用。

【讨论】:

如果我正在实施您的解决方案,是否需要以任何方式修改客户端代码?当我尝试调用新部署的资源时收到消息Uncaught Host must be defined 自去年写这篇文章以来,他们已经进行了一些更新,但理论仍然成立,我需要更多地了解你到底想做什么来帮助你。 没必要,我确定CORS错误实际上只是权限错误被错误标记为CORS错误。 我今天遇到了这个问题,并在 lambda 函数中实现了类似的解决方案:gist.github.com/vtellier/9acb579f81e1a817e182122e8ac2a995 另一个工作是这个插件chrome.google.com/webstore/detail/allow-control-allow-origi/… 可能会有所帮助,但并不严重......

以上是关于API 网关 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

CORS - Api 网关、lambda 和 vue.js [关闭]

对 API 网关的 CORS 请求在浏览器中不起作用

如何使用 AWS API 网关和 Lambda 通过 CORS?

使用 AWS CDK 为 AWS API 网关启用 CORS

从帖子正文读取时,AWS API 网关 CORS 错误

Cors - 如何处理需要自定义标头的预检选项请求? (AWS:使用 vpc 端点的私有 API 网关)