我的应用程序将图像存储在 S3 上,然后通过 Cloudfront 代理它们。我很高兴能够使用新的 S3 CORS 支持,这样我就可以使用 HTML5 画布方法(具有跨域策略),但似乎无法正确配置我的 S3 和 Cloudfront。当我尝试将图像转换为画布元素时,仍然遇到“未捕获的错误:SECURITY_ERR:DOM Exception 18”。
这是我到目前为止所拥有的:
S3
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>MY_WEBSITE_URL</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>MY_CLOUDFRONT_URL</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
云前
起源
Origin Protocol Policy: Match Viewer
HTTP Port: 80
HTTPS Port: 443
行为
Origin: MY_WEBSITE_URL
Object Caching: Use Origin Cache Headers
Forward Cookies: None
Forward Query Strings: Yes
我在这里缺少什么吗?
更新:刚刚尝试将标题更改为
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>
基于这个问题Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading
还是不行。
更新:应要求提供更多信息
Request
URL:https://d1r5nr1emc2xy5.cloudfront.net/uploaded/BAhbBlsHOgZmSSImMjAxMi8wOS8xMC8xOC81NC80Mi85NC9ncmFzczMuanBnBjoGRVQ/32c0cee8
Request Method:GET
Status Code:200 OK (from cache)
更新
我想也许我的请求不正确,所以我尝试启用 CORS
img.crossOrigin = '';
但是随后图像未加载,并且出现错误:跨域资源共享策略拒绝了跨域图像加载。
2014 年 6 月 26 日,AWS 发布了 proper Vary: Origin behavior on CloudFront,所以现在您只需
为您的 S3 存储桶设置 CORS 配置,包括
现在,您的 CloudFront 分配应该为不同的客户端 Origin 标头缓存不同的响应(使用适当的 CORS 标头)。
补充 @Brett's answer。有 AWS 文档页面详细说明了 CORS on CloudFront 和 CORS on S3。
详细的步骤如下:
在您的 S3 存储桶中,转到 Permissions -> CORS configuration 在编辑器中为 CORS 添加规则,
如果您希望缓存 OPTIONS 响应,请执行以下操作: 选择默认缓存行为设置的选项,以启用缓存 OPTIONS 响应。配置 CloudFront 以转发以下标头:Origin、Access-Control-Request-Headers 和 Access-Control-Request-Method。如果您不希望缓存 OPTIONS 响应,请将 CloudFront 配置为转发 Origin 标头以及您的源所需的任何其他标头
https://i.stack.imgur.com/GuoCh.png
使用 CloudFront 和 S3 的 CORS 应该可以工作。
更新:最近对 CloudFront 的更改不再适用。伊皮!有关详细信息,请参阅其他回复。我将这里留给上下文/历史。
问题
CloudFront 不支持 CORS 100%。问题是 CloudFront 如何缓存对请求的响应。此后对同一 URL 的任何其他请求都将导致缓存请求,无论其来源如何。关于这一点的关键部分是它包含来自源的响应标头。
CloudFront 从 Origin: http://example.com
缓存任何内容之前的第一个请求具有以下响应标头:
Access-Control-Allow-Origin: http://example.com
来自 Origin: https://example.com
的第二个请求(注意它是 HTTPS 而不是 HTTP)也具有以下响应标头:
Access-Control-Allow-Origin: http://example.com
因为这是 CloudFront 为 URL 缓存的内容。这是无效的——浏览器控制台(至少在 Chrome 中)将显示一条 CORS 违规消息,并且事情会中断。
解决方法
建议的解决方法是为不同的来源使用不同的 URL。诀窍是附加一个不同的唯一查询字符串,以便每个源有一个缓存记录。
所以我们的 URL 应该是这样的:
http://.../some.png?http_mysite.com
https://.../some.png?https_mysite.com
这种工作,但任何人都可以通过交换查询字符串使您的网站运行不佳。有可能吗?可能不是,但调试这个问题是一个巨大的麻烦。
正确的解决方法是在完全支持 CORS 之前不要将 CloudFront 与 CORS 一起使用。
在实践中
如果您将 CloudFront 用于 CORS,请回退到另一种在 CORS 不可用时有效的方法。这并不总是一种选择,但现在我正在使用 JavaScript 动态加载字体。如果对 CloudFront 的基于 CORS 的请求失败,我会退回到字体的服务器端代理(不是跨源)。这样,即使 CloudFront 以某种方式获得了错误的字体缓存记录,事情仍然可以继续工作。
作为对上一个答案的补充,我想分享有关如何启用 CORS 的 AWS 步骤。我发现它非常有用,提供了额外的链接:https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/
此外,在测试更改时,除了 CloudFront 部署延迟之外,您还应该考虑浏览器缓存。我建议在测试您的更改时使用不同的会话进行隐身。
curl -H "origin: example.com" -v "https://www.anything.net/video/call/System.generateId.dwr"
发布我为使其工作所做的一些重要配置:
将自定义域分配给云端,以便自定义域是您的应用程序前端运行的子域。在 OP 的情况下,他使用的是 localhost:3000;很可能他正在测试他的开发设置,但他必须在某个域部署这个应用程序:让我们称之为“myapp.com”。因此,他可以分配一个自定义域,例如 cdn.myapp.com 以指向 blah.cloudfront.net。您需要为新的自定义域创建/导入自定义 SSL 证书;默认的云端证书不起作用。请参阅:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html
https://i.stack.imgur.com/GUIH7.png
Cloudfront 行为:我假设您已经设置了受信任的密钥组,因为此时您已经拥有签名的 cookie。但是,您将需要创建自定义缓存策略和源请求策略。请参阅以下自定义缓存策略的屏幕截图:和来源请求策略:需要注意的是,您需要将这些标头列入白名单:来源、访问控制请求方法、访问控制允许来源、访问控制-请求标头。 (您可能会注意到 Access-Control-Allow-Origin 不在下拉列表中;只需继续输入它!)。此外,允许所有 cookie。 S3 CORS 配置:转到 S3 存储桶并单击权限选项卡。向下滚动到 CORS 配置。免责声明:我只是粘贴了对我有用的内容。这背后的基本原理是,在我的场景中,这个 S3 将由 CDN 或应用程序访问。我尝试将“*”放宽,但 Chrome 上的 CORS 政策抱怨我不能在 AllowedOrigins 中使用通配符条目!
{“AllowedHeaders”:[“*”],“AllowedMethods”:[“PUT”,“POST”,“GET”,“HEAD”,“DELETE”],“AllowedOrigins”:[“cdn.myapp.com” ,“myapp.com”,“https://cdn.myapp.com”,“https://myapp.com”],“ExposeHeaders”:[“ETag”]}]
react-player:我正在使用这样的 react-player(注意设置了 forceHLS 选项,但它又是针对我的用例的。我认为这通常不是强制性的)
不完全确定您的问题是什么,但是:
https://forums.aws.amazon.com/thread.jspa?messageID=377513
回答了我关于 CORS、S3 和 Cloudfront 的一些问题。
我还发现存储桶中的某些资产会返回正确的 CORS 标头,而有些则不会。在使资产无效后,他们都返回了正确的标题,不知道为什么有些需要无效,而另一些则不需要,因为它们是同时上传的,相同类型的相同存储桶:(
CORS 错误的另一个原因可能是 CloudFront 中配置的 HTTP 到 HTTPS 重定向。
根据文档,CORS 请求中不允许重定向到不同的来源。
例如,如果您尝试访问某些 URL http://example.com,该 URL 具有将 HTTP 重定向到 HTTPS 的云端规则,您将收到 CORS 错误,因为 https://cloudfront.url 被认为是浏览器作为不同的来源。
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSExternalRedirectNotAllowed
我遵循了 AWS 文档:
CloudFront-CORS
S3-CORS
然后我使用 aws cdk 为我做这件事。完整来源:https://github.com/quincycs/quincymitchell.com
const myBucket = new Bucket(this, 'bucket', {
bucketName: `prod-${domainName}`,
cors: [{
allowedMethods: [HttpMethods.GET],
allowedOrigins: ['*'],
allowedHeaders: ['*']
}],
enforceSSL: true,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
removalPolicy: RemovalPolicy.RETAIN
});
const mycert = Certificate.fromCertificateArn(this, 'certificate', ssmCertArn);
new Distribution(this, 'myDist', {
defaultBehavior: {
origin: new S3Origin(myBucket),
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
originRequestPolicy: OriginRequestPolicy.CORS_S3_ORIGIN,
responseHeadersPolicy: ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS,
allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS, // needed for cors
cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS, // needed for cors
},
defaultRootObject: 'index.html',
domainNames: [domainName, `www.${domainName}`],
certificate: mycert
});
2022年答案:
转到您的 S3 存储桶 -> 权限向下滚动到跨域资源共享 (CORS) 应用策略:
[
{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
这将允许来自所有来源的 GET 请求。根据您的项目需要进行修改。
转到您的 CloudFront 分配 -> 行为 -> 编辑(在我的情况下,我只有一个行为)向下滚动到缓存键和源请求选择缓存策略和源请求策略(推荐)在源请求策略下 - 可选选择 CORS-CustomOrigin 保存变化
完毕!
不定期副业成功案例分享
OPTIONS
(通常我相信您会想要),您还应该将Access-Control-Request-Headers
和Access-Control-Request-Method
列入白名单。