放大:即使在 API 网关和 Lambda 标头中启用了 CORS,但 CORS 标头“Access-Control-Allow-Origin”缺失错误

Posted

技术标签:

【中文标题】放大:即使在 API 网关和 Lambda 标头中启用了 CORS,但 CORS 标头“Access-Control-Allow-Origin”缺失错误【英文标题】:Amplify: CORS header ‘Access-Control-Allow-Origin’ missing error even though CORS is enabled in API Gateway and Lambda headers 【发布时间】: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 请求运行良好。 更新了问题以包含更多详细信息。 你找到解决方案了吗? 【参考方案1】:

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

您正在发送一个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上找到显示这些步骤的视频指南

【讨论】:

以上是关于放大:即使在 API 网关和 Lambda 标头中启用了 CORS,但 CORS 标头“Access-Control-Allow-Origin”缺失错误的主要内容,如果未能解决你的问题,请参考以下文章

如何避免通过重新映射无服务器框架从 Lambda 传递回 API 网关的标头?

React.js - CORS 策略:请求的资源上不存在“Access-Control-Allow-Origin”标头。 [AWS - Lambda - API 网关]

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

使用 Rest API Gateway lambda 集成 CORS 问题进行放大

AWS API Gateway按标头信息调用Lambda版本

从 AWS API 网关请求的资源上不存在“Access-Control-Allow-Origin”标头 [重复]