blob.generate_signed_url() 云 URL 偶尔会在几天后返回 SignatureDoesNotMatch

问题描述 投票:0回答:1

当我签署谷歌云存储网址时,该网址会在几天后返回

SignatureDoesNotMatch
,但只是有时。

基于 Cloud Storage 下载 URL 在三天后失败,可能是由于 Content-Type?,我认为添加 content_type 可以修复它。

这是我的代码:

credentials, _project_id = google.auth.default()
storage_client = storage.Client()
bucket = storage_client.bucket(UPLOAD_BUCKET)
blob = bucket.blob(blob_name)

signing_credentials = impersonated_credentials.Credentials(
            source_credentials=credentials,
            target_principal=SERVICE_ACCOUNT_EMAIL,
            target_scopes = 'https://www.googleapis.com/auth/devstorage.read_only',
            lifetime=2 )

url = blob.generate_signed_url(
    version="v4",
    expiration=timedelta(seconds=MEDIA_EXPIRATION), # 7 days is max
    method="GET",
    content_type=blob.content_type, # I think this is setting content_type=None, since blob.reload() is necessary to get a non-None value.
    credentials=signing_credentials
)
# note: I'm not sure if I could have just used credentials=credentials instead of the impersonated_credentials.

一个小旁注:blob.content_type 实际上返回 None。您必须执行

blob.reload()
才能获取 content_type。但是添加 content_type 会导致下载失败,因为浏览器在请求图像时不会在标头中包含 content_type。

python google-app-engine google-cloud-storage
1个回答
0
投票

如所示,Google Cloud Function 中的 getSignedURL() 生成的链接可以运行几天,然后在链接到 https://github.com/googleapis/nodejs-storage/issues/244 的评论中返回“SignatureDoesNotMatch”,一个潜在的原因是 使用默认的 App Engine 服务帐户来签署云存储 blob 。默认服务帐户的密钥经常会轮换,当这种情况发生时,您的所有签名都会被破坏。

为了解决这个问题,我创建了一个具有

Storage Object Viewer

 权限的专用服务帐户,下载了 json 密钥,将其放入我的项目中并直接使用。

SERVICE_ACCOUNT_FILE = 'my-service-account-json-key.json' path = os.path.join(os.path.dirname(__file__), SERVICE_ACCOUNT_FILE) SCOPES = ['https://www.googleapis.com/auth/devstorage.read_only'] credentials2 = service_account.Credentials.from_service_account_file( path, scopes=SCOPES) url = blob.generate_signed_url( version="v4", expiration=timedelta(seconds=MEDIA_EXPIRATION), # 7 days is max method="GET", credentials=credentials2 )
在我的应用中,安全性要求并不高。将资产放入公共桶中是合理的。服务帐户的权限非常有限,只有

Storage Object Viewer

,所以我不担心将私钥包含在我的存储库中。最好将其放入 firestore 或 github Secret 中。

这个特殊问题是邪恶的,因为如果您幸运地掌握了默认 appengine 服务帐户密钥轮换的时间,您的应用程序可以运行数周或数月。如果长期测试发现其他问题,我将更新此内容或删除它。

很多其他答案都谈到过期时间。如果 url 过期,您会收到过期错误,而不是

SignatureDoesNotMatch

。过期时间从来都不是我的问题,除了它不太可能以更长的时间达到默认服务帐户密钥轮换。

© www.soinside.com 2019 - 2024. All rights reserved.