使用 Google Storage 的 CORS 策略允许来自我的来源,但不存在“Access-Control-Allow-Origin"标头

2022-01-25 00:00:00 google-cloud-storage ajax cross-site

我是 CORS 配置的新手并试图解决这个问题,但根据文档,我的设置看起来是正确的.我希望你能帮我看看我错过了什么.我的代码正在尝试使用签名的 url 将文件直接上传 (PUT) 到谷歌存储.

<块引用>

访问 XMLHttpRequest 在'

OPTIONS 调用发生时,Google Storage 正确响应并说它可以支持我的请求方法 GET、HEAD、PUT 和 origin https://herdboss-dev.appspot.com:

<小时>

PUT 请求

但是,当 PUT 发生时,Google Storage 不会以正确的 Access-Control-Allow-Origin 标头响应:

我错过了什么或做错了什么?当我进行直接 http 调用时,我可以使用这些签名的 url 将 PUT 文件直接放入我的 Google Storage 存储桶中,所以我知道签名的 url 有效.我只是遇到了这个 CORS 问题.这对我来说是新事物,我以前没有处理过它,但似乎我正在设置我应该设置的所有东西.

**

我尝试将允许的来源设置为 * 作为测试,但我仍然被相同的 拒绝,请求的资源上不存在Access-Control-Allow-Origin"标头. Chrome 检查器显示 OPTIONS 响应确实发回了我的 * 以获取允许的来源,但它仍然不起作用并且仍然给出相同的错误.

解决方案

想通了.

简短版:Chrome 关于 CORS 的错误消息是一条红鲱鱼.Google 存储拒绝了被解释为违反 CORS 的请求.

长版:

我在 Chrome 的检查器中注意到对我的 PUT 请求的响应的内容长度为 862 个字符,但 Chrome 没有向我显示任何响应.我打开 Firefox 并再次尝试上传过程,但失败并显示有关 CORS 和 Access-Control-Allow-Origin 的相同错误消息.但是,在 Firefox 的网络检查器中,我能够看到原始响应正文!

<错误><代码>SignatureDoesNotMatch</代码><消息>我们计算的请求签名与您提供的签名不匹配.检查您的 Google 密钥和签名方法.</Message><StringToSign>.....</StringToSign><CanonicalRequest>PUT/herdboss-dev.appspot.com/uploads/152/152-owner-152-72.pngX-Goog-Algorithm=GOOG4-RSA-SHA256&amp;....;X-Goog-SignedHeaders=content-type%3Bhost内容类型:图片/png主机:storage.googleapis.com内容类型;主机未签名有效载荷</CanonicalRequest></错误>

我的理论是,当 Chrome 和 Firefox 进行飞行前 CORS 检查,然后发出 PUT 请求并收到 403 响应代码时,它正在响应,就好像这是一个 CORS 问题,即使该问题与 CORS 无关,并且预检响应 DID 实际上有 Access-Control-Allow-Origin 标头.

从这里,我可以通过检查我的 url 签名代码与请求来快速诊断问题.我注意到,在创建签名上传 url 时,我需要 application/octet-streamContent-type 但是当浏览器中的 javascript 正在执行 PUT 请求将 Content-type 设置为 image/png.我更新了我的 javascript 以强制 Content-type 匹配 application/octet-stream 然后请求成功.

I'm new to CORS configuration and trying to figure this out, but my set up looks like it is right according to the documentation. I'm hoping you can help me see what I've missed. My code is trying to upload (PUT) a file directly to google storage using a signed url.

Access to XMLHttpRequest at 'https://storage.googleapis.com/herdboss-dev.appspot.com/uploads/152/152-owner-152-61.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Go...' from origin 'https://herdboss-dev.appspot.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I've set the CORS policy on my Google Storage Bucket (added line breaks for readability):

% gsutil cors get gs://herdboss-dev.appspot.com               
[{
"maxAgeSeconds": 3600, 
"method": ["GET", "HEAD", "PUT"], 
"origin": ["https://herdboss-dev.appspot.com"], 
"responseHeader": ["X-Requested-With", "Access-Control-Allow-Origin", "Content-Type"]
}]

According to my chrome inspector, the pre-flight request happens and returns the proper methods and headers (as far as I can tell). Also, as a side note, I noticed the PUT shows up in my Chrome inspector before the OPTIONS, but the timestamps show the OPTIONS is sent first.

When the OPTIONS call happens, Google Storage correctly responds and says it can support my request methods GET, HEAD, PUT and origin https://herdboss-dev.appspot.com:


THE PUT REQUEST

However, when the PUT happens, Google Storage does not respond with the proper Access-Control-Allow-Origin header:

What am I missing or doing wrong? I'm able to use these signed urls to PUT files directly into my Google Storage bucket when I make a direct http call, so I know the signed urls work. I'm just running into this CORS problem. It's a new thing for me, I haven't dealt with it before, but it seems like I'm setting all of the things I should be setting.

**EDIT 1:

I tried setting my allowed origins to * just as a test and I was still rejected with the same No 'Access-Control-Allow-Origin' header is present on the requested resource. The Chrome inspector showed the OPTIONS response did send back my * for allowed origins, but it still didn't work and still gave the same error.

解决方案

Figured it out.

Short version: Chrome's error message about CORS was a red herring. Google Storage was rejecting the request which was being interpreted as a CORS violation.

Long version:

I noticed in Chrome's inspector that the response to my PUT request had a content length of 862 characters, but Chrome wasn't showing me any response. I opened Firefox and tried the upload process again and it failed with the same error messages about CORS and Access-Control-Allow-Origin. However, in Firefox's network inspector, I was able to see the raw response body!

<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
    <StringToSign>.....</StringToSign>
    <CanonicalRequest>PUT
/herdboss-dev.appspot.com/uploads/152/152-owner-152-72.png
X-Goog-Algorithm=GOOG4-RSA-SHA256&amp;....;X-Goog-SignedHeaders=content-type%3Bhost
content-type:image/png
host:storage.googleapis.com

content-type;host
UNSIGNED-PAYLOAD
    </CanonicalRequest>
</Error>

My theory is that when Chrome and Firefox do the pre-flight CORS checking and then issue the PUT request and receive a 403 response code that it is responding as if it is a CORS problem even though the problem was not CORS related and the preflight response DID actually have the Access-Control-Allow-Origin header.

From here, I was able to quickly diagnose the problem by checking my url signing code against the request. I noticed that when created the signed upload url that I was requiring a Content-type of application/octet-stream but when the javascript in the browser was doing the PUT request that it was setting the Content-type to image/png. I updated my javascript to force the Content-type to match application/octet-stream and then the request succeeded.

相关文章