【发布时间】:2020-12-28 10:58:50
【问题描述】:
在 Angular 9 应用程序中,当我将此图像缓存 sn-p 添加到 ngsw-config.json 时,出现 CORS 错误并且图像不显示。如果我删除这个 sn-p 应用程序可以正常工作(没有错误)。
访问“https://assets.myurl.net/images/banner.jpg”从 来源 'https://localhost:8100' 已被 CORS 策略阻止:否 请求中存在“Access-Control-Allow-Origin”标头 资源。如果不透明的响应满足您的需求,请设置请求的 模式为“no-cors”以获取禁用 CORS 的资源。
ngsw-config.json (sn-p):
"assetGroups": [{
"name": "cdn",
"installMode": "lazy",
"updateMode": "lazy",
"resources": {
"urls": [
"https://assets.myurl.net/**"
]
}
}]
图像存储在具有 CORS 配置的 AWS S3 存储桶中:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
- Cloudflare 被用作 CDN(和 DNS)。
- 该应用程序是最新的 9.x 版本:@angular 9.2.1、@angular/service-worker 9.1.12.
- 向 img 和图片标签添加 crossorigin="anonymous" 似乎没有帮助。
在 Chrome/PC 中持续重现错误的步骤:
- 清除浏览器缓存
- 以私密/隐身方式打开浏览器
- 转到网站 -- 图片显示正常
- 点击刷新 - 图像不再显示 - 浏览器控制台中出现 CORS 错误
更新
根据这篇文章 (S3 not returning Access-Control-Allow-Origin headers?),问题似乎是服务工作者没有在请求标头中发送 Origin(因此 S3 不发送访问控制标头)。
Service Worker 请求(从 Chrome 控制台复制):
Request URL: https://assets.myurl.net/images/banner.jpg
Referrer Policy: strict-origin-when-cross-origin
Provisional headers are shown
Referer: https://localhost:8100/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
首先,确保每个请求都有一个 Origin 标头。如果没有 Origin 标头 已发送,S3 不会发送访问控制标头,因为 S3 认为它们 不相关(通常情况下,它们是)。浏览器(CORS 机制的意思)将自动发送一个 Origin 标头时 通过 XMLHTTPRequest 进行跨域 HTTP 请求。
根据这篇文章 (S3 - Access-Control-Allow-Origin Header),S3 cors 脚本已更新为包括:
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
向 img 标签添加 crossorigin="anonymous" 不会更改 service worker 请求标头。所以这并不能解决问题。
Cloudflare 缓存已被清除。
这个不起眼的帖子 (https://community.cloudflare.com/t/access-control-allow-origin-headers-stripped/158102/2) 包括:
如果您在源 Web 服务器上添加或更改 CORS 配置, 通过 URL 清除 Cloudflare 缓存不会更新 CORS 标头。
我通过添加随机查询字符串(即banner.jpg?q=abc)缓存了banner.jpg 图像。横幅图像始终正确显示(而其他图像仍显示 cors 错误)。 Chrome 控制台应用程序选项卡 > 缓存存储中的服务工作者缓存显示图像已缓存。 Cloudflare 缓存配置“缓存级别”= 标准“每次查询字符串更改时交付不同的资源”。
但是,如果我将新图像上传到 S3 banner01.jpg(即尚未被 Cloudflare 缓存),我确实会收到显示此图像的 cors 错误。 我通过上传不同的图像又尝试了 3 次图像名称,并没有得到一个 cors 错误。有趣的是,一个小时后,即使是新图像也显示 cors 错误。
curl 命令(未在标头中指定 Origin)在我的本地 PC 上成功运行。响应不包含 CORS 标头。例如
curl -v "https://assets.myurl.net/images/banner.jpg"
向 curl 命令添加源会返回 CORS 标头。例如
curl -v --header "Origin: https://www.example.com" "https://assets.myurl.net/images/banner.jpg"
access-control-allow-origin: https://www.example.com
access-control-allow-methods: GET, HEAD
access-control-allow-credentials: true
更新 2
我无法解释原因,但 Chrome 现在会在 Angular Service Worker 获取响应中返回 cors 标头。该请求不包含 Origin 标头。
accept-ranges: bytes
access-control-allow-methods: GET, HEAD
access-control-allow-origin: *
但是,Safari 没有。所有浏览器似乎都可以正常工作,但 Safari 仍然显示 cors 错误。
【问题讨论】:
-
嗨,你确定你不需要为预检请求允许“OPTIONS”吗?
-
这篇文章中的措辞有点含糊 (docs.aws.amazon.com/AmazonS3/latest/dev/cors.html) 但对于规则“
* ”它声明“该规则还允许预检 OPTIONS 请求中的所有标头” .所以我已将此 cors 规则添加到 S3 并更新了问题。 -
有人说他们将允许的来源从“*”更改为“https://*”和“http://*”,试试看。
-
顺便问一下,您确定您的 OPTIONS 标头没有被 cloudfront 缓存吗?
-
同意 - 我认为 Cloudflare 正在缓存 cors 标头,并且正在使用旧 S3 cors 设置中的旧标头。我尝试过的任何操作似乎都无法清除此缓存(我只能重命名图像以解决该问题)。 support.cloudflare.com/hc/en-us/articles/…
标签: angular cors service-worker