使用 Google App Engine 签名的 Google Cloud Storage 网址
Posted
技术标签:
【中文标题】使用 Google App Engine 签名的 Google Cloud Storage 网址【英文标题】:Google Cloud Storage Signed URLs with Google App Engine 【发布时间】:2014-03-22 00:00:42 【问题描述】:处理 Google Cloud Storage 的常规 Signed URLs (Query String Authentication) 令人沮丧。
Google Cloud Storage Signed URLs Example -> 这真的是整个互联网上唯一可用于为 Google Cloud Storage 生成签名 URL 的代码吗?如果需要,我应该全部阅读并手动调整它以适应 Pure Python GAE 吗?
当你将它与已经包含在任何 SDK 中的 AWS S3 getAuthenticatedURL() 进行比较时,这太荒谬了......
我是否遗漏了一些明显的东西,还是每个人都面临同样的问题?有什么关系?
【问题讨论】:
为什么首先需要一个签名的 URL? @AndreiVolgin 我不想要求我的用户拥有谷歌帐户。我只需要临时经过身份验证的 URL。 @AndreiVolgin 这是一个有趣的解决方案,但我必须以这种方式支付例如几个小时的费用,而不是直接从 GCS 提供文件。如果我的应用没有托管在 GAE 中,我还必须支付网络传输费用... 如果您有很多用户,请使用 Compute Engine 实例 - 它便宜很多倍。如果您还没有很多用户,您可能在 GAE 的免费配额内。 【参考方案1】:我不知道为什么the docs 如此糟糕。 SO上唯一的另一个comprehensive answer很棒但很乏味。
输入generate_signed_url method。爬下兔子洞,您会注意到使用此方法时的代码路径与在 GAE 上执行时上述 SO 帖子中的解决方案相同。然而,这种方法不那么繁琐,支持其他环境,并且有更好的错误消息。
在代码中:
def sign_url(obj, expires_after_seconds=60):
client = storage.Client()
default_bucket = '%s.appspot.com' % app_identity.get_application_id()
bucket = client.get_bucket(default_bucket)
blob = storage.Blob(obj, bucket)
expiration_time = int(time.time() + expires_after_seconds)
url = blob.generate_signed_url(expiration_time)
return url
【讨论】:
【参考方案2】:我最近也遇到了这个问题,并找到了使用内置服务帐户在 GAE 中的 python 中执行此操作的解决方案。使用 google.appengine.api.app_identity 包中的 sign_blob() 函数对签名字符串进行签名,并使用同一包中的 get_service_account_name() 来获取 GoogleAccessId 的值.
不知道为什么文档记录这么差,即使现在知道这可行,我也无法使用 Google 搜索找到任何提示,应该可以为此目的使用内置帐户。不过很好用!
【讨论】:
非常感谢。这很好用,没有 pycrypto。即使在 SDK 上。 我的代码在这里:***.com/questions/29847759/…【参考方案3】:如果您不想自己编写,请在 GitHub 上查看该课程。
非常好用
GCSSignedUrlGenerator
【讨论】:
【参考方案4】:以下是在 Go 中的操作方法:
func GenerateSignedURLs(c appengine.Context, host, resource string, expiry time.Time, httpVerb, contentMD5, contentType string) (string, error)
sa, err := appengine.ServiceAccount(c)
if err != nil
return "", err
expUnix := expiry.Unix()
expStr := strconv.FormatInt(expUnix, 10)
sl := []string
httpVerb,
contentMD5,
contentType,
expStr,
resource,
unsigned := strings.Join(sl, "\n")
_, b, err := appengine.SignBytes(c, []byte(unsigned))
if err != nil
return "", err
sig := base64.StdEncoding.EncodeToString(b)
p := url.Values
"GoogleAccessId": sa,
"Expires": expStr,
"Signature": sig,
return fmt.Sprintf("%s%s?%s", host, resource, p.Encode()), err
【讨论】:
【参考方案5】:查看https://github.com/GoogleCloudPlatform/gcloud-python/pull/56
在 Python 中,这确实...
import base64
import time
import urllib
from datetime import datetime, timedelta
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from OpenSSL import crypto
method = 'GET'
resource = '/bucket-name/key-name'
content_md5, content_type = None, None
expiration = datetime.utcnow() + timedelta(hours=2)
expiration = int(time.mktime(expiration.timetuple()))
# Generate the string to sign.
signature_string = '\n'.join([
method,
content_md5 or '',
content_type or '',
str(expiration),
resource])
# Take our PKCS12 (.p12) key and make it into a RSA key we can use...
private_key = open('/path/to/your-key.p12', 'rb').read()
pkcs12 = crypto.load_pkcs12(private_key, 'notasecret')
pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkcs12.get_privatekey())
pem_key = RSA.importKey(pem)
# Sign the string with the RSA key.
signer = PKCS1_v1_5.new(pem_key)
signature_hash = SHA256.new(signature_string)
signature_bytes = signer.sign(signature_hash)
signature = base64.b64encode(signature_bytes)
# Set the right query parameters.
query_params = 'GoogleAccessId': 'your-service-account@googleapis.com',
'Expires': str(expiration),
'Signature': signature
# Return the built URL.
return 'endpointresource?querystring'.format(
endpoint=self.API_ACCESS_ENDPOINT, resource=resource,
querystring=urllib.urlencode(query_params))
【讨论】:
谷歌应用引擎python有类似的东西吗? gcloud 的开销似乎太大了? 我只是稍微考虑了一下——错误是“ImportError:没有名为 OpenSSL 的模块”——但是你只是使用加密将 p12 转换为 pem 密钥,所以我只是将离线生成我的 pem 密钥并将其上传到应用程序引擎。所以我应该能够删除那些依赖项以上是关于使用 Google App Engine 签名的 Google Cloud Storage 网址的主要内容,如果未能解决你的问题,请参考以下文章
在 Google-App-Engine 中使用 HSQLDB
如何在 Google Cloud App Engine 上使用 PubSub 创建订阅者,该订阅者通过 Publisher 从 Google Cloud App Engine Flex 收听消息?
是否可以将 Google App Engine 与 Google Cloud *** 一起使用?
Google App Engine 通过内部网络与 Compute Engine 通信