【发布时间】:2019-07-03 20:48:59
【问题描述】:
简介
为了对我的多租户系统上的所有客户端保持上传的媒体(S3 对象)的私有性,我实施了 Cloudfront CDN 部署并将其(及其源 S3 存储桶)配置为强制按顺序使用签名 URL获取任何对象。
方法
首先,通过我的系统对用户进行身份验证,然后使用AWS JS SDK 提供的AWS.CloudFront.Signer.getSignedUrl() 方法生成签名的URL 并返回给他们。因此他们可以调用 CF/S3 来下载对象(图像、PDF、docx 等)。很标准的东西。
问题
上述方法在 95% 的时间内都有效。用户从我的系统中获取了一个签名的 URL,然后当他们使用 XHR 来获取对象时,它就被检索到了。
但是,有 5% 的时间会抛出 403 并带有 CORS 错误,指出客户端来源 is not allowed by Access-Control-Allow-Origin。
此错误(错误)已在所有环境中得到确认:localhost、dev.myapp.com、prod.myapp.com。并且跨所有平台/浏览器。
它缺乏韵律或理由,以至于我实际上开始认为这是一个 AWS 错误(它们确实会发生,不时发生)。
到目前为止的调试清单
我这几天一直在想办法解决这个问题。到目前为止,这是我尝试过的:
您是否尝试过其他浏览器/平台?
是的。该问题存在于所有客户端来源、浏览器(和 版本)和所有平台。
您的 S3 存储桶是否为 CORS 正确配置?
是的。事实上,它是敞开的。我什至设置了
<MaxAgeSeconds>0</MaxAgeSeconds>为了防止缓存任何飞行前OPTIONS请求 客户:签名的 URL 是否过期?
不。所有签名的 URL 都设置为在生成后 24 小时过期。这个问题甚至出现了几秒钟 在生成任何给定的签名 URL 之后。
生成签名 URL 的方法是否存在问题?
不太可能。我只是使用
AWS.CloudFront.Signer.getSignedUrl()他们的 JS SDK 的方法。签名的网址确实大部分时间都有效,所以 签名会是个问题,这似乎很奇怪 过程。此外,该错误显然是 CORS 错误,而不是签名 不匹配错误。是时区/服务器时钟问题吗?
不。该系统确实为多个时区的用户提供服务,但是 鉴于签名的 URL 都是生成的,理论被证明是错误的 在服务器端。客户端的时区无关紧要,它得到 一个签名的 URL 从生成之日起 24 小时内有效,无论如何 TZ 进去了
您的 CF 发行版配置正确吗?
是的,据我跟踪几个AWS guides, tutorials, docs and such.
为了简洁起见,这是一个屏幕截图。你可以看到我已经禁用 完全缓存以试图将其排除为原因:
您是否看到所有 mime 类型的错误?
没有。没有任何图像、音频或视频文件出现此错误 (对象)。已经完成了很多测试,这个错误似乎只是 尝试获取文档或 PDF 文件(.doc、.docx、 .pdf)。这让我相信这只是一个
Accept标头 不匹配错误:客户端正在发送带有标头的 XHRAccept: pdf,但实际上签名是为Accept: application/pdf生成的。 我还不能完全排除这种情况 原因。但鉴于错误是极不可能的 间歇性的。因此,如果它是Accept标头不匹配问题,那么它 每次都应该是一个错误。此外,XHR 正在发送
Accept: */*,因此这不太可能是问题所在。
问题
我真的在这个问题上碰壁了。谁能看到我在这里缺少的东西?我能想到的最好的办法是这是某种“时间”问题。什么样的时间问题,或者甚至是时间问题,我还没有弄清楚。
提前感谢您的帮助。
【问题讨论】:
-
如果
Access-Control-Allow-Origin不允许来源 " 那么紧迫的问题似乎是Access-Control-Allow-Origin实际上包含什么? 和,还包括哪些其他响应标头?除了任何 CORS 标头之外,特别感兴趣的还有Age、X-Cache和Server。 -
"客户端发送的 XHR 带有标头
Content-Type: pdf" ...这是一个令人困惑的声明,因为客户端不应该发送 any 带有GET请求的Content-Type标头。Content-Type请求头指定请求体的MIME类型,GET请求没有请求体。 -
@AJB 你在这方面有什么进展吗?我遇到了完全相同的问题,除了我什至没有使用 CloudFront(服务器返回签名的 S3 url,浏览器对该 URL 执行 PUT)。它只发生大约 5-10% 的时间,而且我的 CORS 也是完全开放的。
-
我们面临同样的问题。不是一个实际的解决方案,但使 Cloudfront 缓存无效可以解决问题。我们计划添加一个监控脚本,该脚本会经常检查这一点,并在出现故障时使缓存失效。
-
@AndresEspinosa 不幸的是,我没有。我确实尝试了下面 Abishak Garg 的回答中概述的解决方案,但它对我不起作用。不过,调查链接的 ServerFault 问题也是值得的。 (如果您找到可靠的解决方案,请发布!)
标签: amazon-web-services amazon-s3 amazon-cloudfront pre-signed-url