使用 Lambda、API Gateway 和 Cloudfront 时,尽管在 Lambda 响应中指定了“Access-Control-Allow-Origin”,但 CORS 错误
Posted
技术标签:
【中文标题】使用 Lambda、API Gateway 和 Cloudfront 时,尽管在 Lambda 响应中指定了“Access-Control-Allow-Origin”,但 CORS 错误【英文标题】:CORS error despite 'Access-Control-Allow-Origin' specified in Lambda response when using Lambda, API Gateway and Cloudfront 【发布时间】:2019-02-22 13:58:01 【问题描述】:我有一个已部署的 Web 应用程序,它使用托管在 S3 上的 React 和 Redux 前端构建,以及托管在 AWS Lambda 上并通过 API Gateway 公开的多个后端微服务,这些微服务是使用 Serverless 部署的。该网站还通过 CloudFront CDN 分发。
微服务与多个外部服务交互,但我关心的主要服务是 get-products
服务,它查询 Stripe 产品数据库并将产品从那里返回到我的 React 应用程序。
网站一直运行良好,直到昨天我为前端部署了一些新的(基本上是装饰性的)更改,并向 Stripe 数据库添加了更多 SKU。自从添加这些更改后,我开始遇到以前没有的 CORS 错误。
最初我收到以下错误:
Access to XMLHttpRequest at 'https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/dev/products' from origin 'https://www.superfunwebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
尽管我的 Lambda 响应包含以下标题:
'Access-Control-Allow-Origin': '*',
此时,我将 Lambdas 响应标头更新为以下内容:
'Access-Control-Allow-Origin': 'https://www.superfunwebsite.com/',
'Access-Control-Allow-Credentials': true
该错误基本上一直存在,除了在一个随机页面加载时,我收到一个错误,指出 Origin https://www.superfunwebsite.com
和 'Access-Control-Allow-Origin' https://www.superfunwebsite.com/
不匹配。
我已经将 Lambda 响应标头更改为:
'Access-Control-Allow-Origin': 'https://www.superfunwebsite.com',
'Access-Control-Allow-Credentials': true
这似乎已经解决了异常的第二个错误。
但是,即使我使用 Insomnia 等 HTTP 客户端进行测试,错误仍然存在。我在响应中得到以下内容。
// status code
403
// response
"message": "Forbidden"
// headers
Content-Type: application/json
Content-Length: 23
Connection: keep-alive
Date: Tue, 18 Sep 2018 13:22:41 GMT
x-amzn-RequestId: eb691541-bb45-11e8-82ff-6d1b542dffb9
x-amzn-ErrorType: ForbiddenException
x-amz-apigw-id: NaxVLGJgjoEF5Fg=
X-Cache: Error from cloudfront
Via: 1.1 08037e15a3c6f503f39825efeb7f0210.cloudfront.net (CloudFront)
X-Amz-Cf-Id: cbNtb4xKWc48VPFon-Cl9y27KmXRVLIN5SWuYwNWlWsTXeaAXx3z-Q==
根据上面的 Insomnia 输出,我的问题似乎与 CloudFront 有某种关系,尽管我不明白具体如何。 This other S/O post 似乎表明 CloudFront 行为部分中应该有适合我的选项,允许我将响应的标头列入白名单,但是这些选项在控制台中对我不可见,我看到了建议,这是因为来源在 S3。
我的问题很简单,是否有人知道我可以如何解决此问题,或者是否还有其他我认为不应该考虑的东西?
【问题讨论】:
更新 - 我现在还使用 API Gateway 控制台的测试功能对此进行了测试。此处响应成功返回,正确的标头完好无损: Access-Control-Allow-Origin: superfunwebsite.com 【参考方案1】:在这里,您必须在云端分发的行为部分中将相应的 CORS 标头列入白名单。
-
从 Amazon CloudFront 控制台打开您的分配
选择“行为”视图。
选择创建行为,或选择现有行为,然后选择编辑。
对于选项
Cache Based on Selected Request Headers
,选择白名单。
在白名单标头下,从左侧菜单中选择标头(Access-Control-Request-Headers
和 Access-Control-request-methods
、Origin
),然后选择添加。
选择是,编辑。
上述设置应该适合您(因为它主要适用于GET
和HEAD
),但如果不适合,请使用下面的文章启用 OPTIONS 方法。
请查看以下来自 aws 的文章:
no-access-control-allow-origin-error
Custom CORS Cloudfront
enhanced-cloudfront-customization
【讨论】:
谢谢!Access-Control-Request-Headers
和 Access-Control-Request-Methods
没有出现在我的左侧菜单中,但我选择尝试通过 Add Custom
输入添加它们。手指交叉这个修复它。
@Josh 奇怪的是标题不存在。我刚刚检查了我的分发控制台,那些标题就在那里。在您确认所有设置都正常后,也请接受答案。
是的,我想我读到这与托管在 S3 上的站点有关,但是我现在找不到此信息。不幸的是,这似乎不起作用,因为我在进行更改时将行为 TTL 降至两分钟,但我仍然遇到同样的问题。
@Josh 有许多用例,解决方案会有所不同。但简而言之,需要 CORS 标头才能成功允许所需的内容。
感谢您的意见 Sangam。我现在已经解决了这个问题,事实证明这实际上不是 CORS 问题,但由于错误消息,我被引导相信这一点。实际上,我遇到了一个暂存问题,导致我查询了一个不存在的端点。【参考方案2】:
这个问题现在已经解决了。最后,这实际上不是 CORS 问题,而是分期问题。我的查询失败了,因为我正在查询一个不存在的端点阶段。
似乎在我使用 CloudFront 和 API Gateway 的设置中,当查询一个不存在的端点时,我收到了一个没有 CORS 标头的 403
响应。
浏览器/CloudFront(不确定是哪个)随后识别出缺少 CORS 标头并引发错误以响应该问题。
在我的情况下,只需从开发阶段更改我的端点(与实时阶段关联的关联 AWS 账户上不存在该端点):
https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/dev/products
到现场:
https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/live/products
立即解决了问题。
【讨论】:
以上是关于使用 Lambda、API Gateway 和 Cloudfront 时,尽管在 Lambda 响应中指定了“Access-Control-Allow-Origin”,但 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 AWS API Gateway 和 Lambda 的地理定位服务
AWS Lambda 和 Gateway API - 使用 cloudformation 的蓝/绿部署
在 Lambda 中获取用户的 IP 地址(使用 API Gateway 和 Python)
AWS Lambda 和 API Gateway 响应集成问题