【问题标题】:Amplify: CORS header ‘Access-Control-Allow-Origin’ missing error even though CORS is enabled in API Gateway and Lambda headers放大:即使在 API 网关和 Lambda 标头中启用了 CORS,但 CORS 标头“Access-Control-Allow-Origin”缺失错误
【发布时间】:2020-07-27 02:22:13
【问题描述】:

我正在使用 Amplify,并让我的 API 网关代理到 Lambda。我在 /{proxy+} 上启用了 CORS 并部署了 API。在我的 Lambda 函数中,我在我的普通函数中设置了适当的标头:

import json


def handler(event, context):
    print("received event:")
    print(event)
    return {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Credentials": True,
            "Access-Control-Allow-Headers": "Content-Type",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET",
            "Access-Control-Allow-Origin": "*",
        },
        "body": json.dumps(event),
    }

此 Lambda 函数位于通过 Cognito 进行身份验证的 API Gateway 资源后面。

当我使用 Amplify 调用我的 API 时:

let myInit = {
          headers: {
            Authorization: `Bearer ${(await Auth.currentSession())
              .getIdToken()
              .getJwtToken()}`
          }
        }; 

API.get("adminapi", "/admin", myInit) ...

我的GET 请求中缺少可怕的 CORS 标头“Access-Control-Allow-Origin”:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/admin. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

我看到它在OPTIONS 请求中返回:

我什至在 Postman 中进行了测试以验证标头是否会返回:

我在这里做错了什么?调用似乎没有通过 API 网关。我想知道它是否与身份验证有关。当我使用我的 IAM 凭证从 Postman 进行测试时,它可以正常工作,但是从我的 Web 应用程序使用不记名令牌时,它会像上面一样失败。

【问题讨论】:

  • 总是引用 full 错误消息。我怀疑它说预检响应中缺少标头,而不是请求的资源。
  • GET 请求中缺少标头。 OPTIONS 请求运行良好。
  • 更新了问题以包含更多详细信息。
  • 你找到解决方案了吗?

标签: cors aws-amplify amplifyjs aws-amplify-vue


【解决方案1】:

我假设您忘记处理用于 preflight requestOPTIONS 动词并在那里返回标题。

您正在发送一个Authorization 标头,它不在"simple" requests 的允许标头列表中,因此preflighted request 已完成。

此外,为了credentials to get through,您必须确保也设置了Access-Control-Allow-Credentials: true 标头。

从代码 sn-p 中看不出您的请求正文是什么内容类型,但如果不是application/x-www-form-urlencodedmultipart/form-datatext/plain(比如application/json),您还需要将其列入白名单Content-Type 标头使用Access-Control-Allow-Headers: Content-Type

【讨论】:

  • OPTIONS 正在处理(某处),因为它返回 access-control-allow-origin: *。我更新了我的函数以在响应标头中包含"Access-Control-Allow-Credentials": True。同样的情况。 Access-Control-Allow-Headers 在 API Gateway 中默认设置为 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
  • 如果你把 Fiddler 放在中间会发生什么?检查实际超出范围的内容以及它与您的测试有何不同。也许您在服务器中遇到错误(例如身份验证无效),然后不会返回这些标头(因为您似乎只在状态为 200 的成功案例中返回它们)?也许您的授权标头没有发送,因为您的库没有将withCredentials: true 传递给 XHR...
【解决方案2】:

我遇到了同样的问题。我的飞行前OPTIONS 请求具有所有正确的标头:

access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
access-control-allow-origin: *

所以我添加后浏览器开始接受请求

access-control-allow-origin: *

对我想使用的实际方法的请求的响应(非预检,例如:GETPOST等方法)

【讨论】:

    【解决方案3】:

    当我从我的 API Gateway OPTIONS 端点中删除 Cognito 身份验证时,在 js 中使用 fetch() 时,它起作用了。 Chrome 和 Firefox 不会将 Authorize 标头发送到 OPTIONS。不过,放大可能会有所不同。引用:https://fetch.spec.whatwg.org/#http-responses...

    "For a CORS-preflight request, request’s credentials mode is always "same-origin", i.e., it excludes credentials, but for any subsequent CORS requests it might not be."
    

    【讨论】:

      【解决方案4】:

      我刚刚遇到过类似的事情。这里的问题询问为什么浏览器在使用 Amplify 访问 API 网关时返回 CORS 错误,尽管在端点中正确配置了 CORS 标头。

      除了不正确的 CORS 标头配置之外,如果请求的某些方面不正确,Amplify/API Gateway 会给出 CORS 错误。我遇到的有:

      • 您使用的 HTTP 谓词不存在于端点上
      • 您使用的端点不存在(例如拼写错误)
      • Content-Type 标头不正确

      后者给我带来了问题。似乎Amplify.API.postAmplify.API.put 默认都发送application/x-www-form-urlencoded 的Content-Type。我的 API 期待 application/json,结果是 CORS 错误。

      【讨论】:

        【解决方案5】:

        在我使用 Amplify 并尝试保护 API 网关,使其只有通过 Cognito 登录的用户才能访问时,我遇到了同样的问题。

        您可能也错过了我错过的步骤是 AWS API-Gateway 中的一些配置。您需要转到网关仪表板并创建一个使用您的 Cognito 用户池的“授权者”。 token source 将是您为此使用的任何标题标签(通常是“授权”)。

        但你还没有完成。然后,您需要转到“资源”并更改方法请求以使用您刚刚创建的新授权方。

        希望在做完这一切之后,你应该会没事的。如果您的用户已登录,并且您按原样添加 Authorization 标头:

        let myInit = {
                  headers: {
                    Authorization: `Bearer ${(await Auth.currentSession())
                      .getIdToken()
                      .getJwtToken()}`
                  }
                };
        

        希望一切顺利。

        可以在here on Youtube, and starting around 10:50上找到显示这些步骤的视频指南

        【讨论】:

          猜你喜欢
          • 2021-12-02
          • 1970-01-01
          • 2019-06-19
          • 2018-03-28
          • 2020-01-05
          • 2021-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多