【发布时间】:2021-09-30 06:46:59
【问题描述】:
我正在使用签名的 url 在我的谷歌存储上获取或发布/发布视频 fileq。我的模块在signed_url V4 上引用,并且运行良好。 我想在我的请求中添加一些元数据标签,以便更有效地管理与 GCS 相关的费用。但是由于我添加了这些标头,因此请求未能返回 cors 策略错误:(我已缩短上面块中的签名以使其更具可读性)
Access to XMLHttpRequest at 'https://test-dev-slotll.storage.googleapis.com/uploads/dave/FR/eaa678c9/2020/9/785f/f45d3d82-785f_full.mp4?X-
Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=dev-storage%40brilliant-tower-264412.iam.gserviceaccount.com%2F20200926%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20200926T093102Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host%3Bx-goog-meta-account&x-goog-signature=6fbb27e[...]bd0891d21' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
以及详细信息:
<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>x-goog-meta-account</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>
cors 被配置为允许我存储桶上的几乎所有东西:
[{"maxAgeSeconds": 3600, "method": ["*"], "origin": ["*"], "responseHeader": ["*"]}]
这里是 Python/Django 函数
def _get_signed_url(self, http_method="GET"):
"""' create a signed url with google storage
create a 'GET' request by default,
add method='w' or 'put' to create a 'PUT' request
get_signed_url('w')->PUT / get_signed_url()->GET
"""
if http_method.lower() in ["w", "put", "post"]:
http_method = "PUT"
else:
http_method = "GET"
signed_url = generate_signed_url(
settings.GS_BUCKET_NAME,
self.file.name,
subresource=None,
expiration=3600,
http_method=http_method,
query_parameters=None,
headers={'x-goog-meta-language':'french','x-goog-meta-account':'david',},
)
return signed_url
正如我在上面写的,get_signed_url() 方法是从signed_url V4 复制而来的
如果我替换headers = {'x-goog-meta-language':'french','x-goog-meta-account':'david',},
hearders = {} 或 headers = None (就像以前一样,它工作正常
最后,当我点击签名网址给出的链接时,我收到一条错误消息:
签名的 url 以及 blob 上传或下载在没有标头的情况下可以正常工作几个月,但我不明白为什么服务器会响应标头元标记格式错误... 我将不胜感激 谢谢!
【问题讨论】:
-
如果您修复了 MalformedSecurityHeader 错误的原因,您可能会发现您现有的 CORS 配置已经按预期工作。当响应状态不是 200 OK 而是一些错误时,这是正常的,并且预期响应不会有 Access-Control-Allow-Origin 响应头。
-
是的,我不怀疑 cors。当我不发送额外的标头并且所有内容都通过 cors 授权时,签名的 url 有效。我不明白为什么我的元数据格式错误以及为什么 headers = {'x-goog-meta-language':'fr'} 不正确...
-
我对 Google Cloud 的知识了解为零,但我确实注意到问题中引用的错误是,“标头包含在签名标头中,但未包含在请求中。” i> 这似乎表明问题不在于标头的值格式不正确,而是请求标头完全丢失了。因此,您可能想要更新问题以显示发出请求的前端 JavaScript 代码部分的 sn-p。该代码是否确保正确的标头包含在请求中?
-
我找到了stackoverflow.com/questions/56779529/…,这似乎与您遇到的问题相同。那里删除的答案说,“这个错误意味着您在创建签名时包含了 HTTP 标头
。这意味着客户端在上传时也必须包含此标头。在签名之前删除标头或修改客户端软件以在发出 HTTP 请求时包含 标头。” -
我了解到问题出在 HTTP 请求上。但是该 URL 是由 GCP 通过“签名的 url v4 脚本”提供的“generate_signed_url()”方法构建的。我只是通过 django 模板将给定的 URL 发送给客户端,该模板“打印”带有签名 URL 的链接。当用户单击该 URL 给出的链接时,客户端会发送一个 GET 请求。由于链接本身无法修改请求,如何在请求中插入标头?
标签: python django google-cloud-platform google-cloud-storage