10

处理Google云端存储的常规Signed URLs (Query String Authentication)令人沮丧。使用Google App Engine的Google云端存储签名URL

Google Cloud Storage Signed URLs Example - >这是否真的是整个互联网上唯一可用于生成Google Cloud Storage签名URL的代码?我是否应该阅读所有内容,并根据需要手动修改纯Python GAE?

当你与AWS S3 getAuthenticatedURL(),已经包含在任何SDK进行比较这是荒谬的......

我失去了一些东西明显或每个人都面临着同样的问题?这是怎么回事?

+0

为什么你需要摆在首位签署的网址是什么? –

+1

@AndreiVolgin我不想要求我的用户拥有Google帐户。我只需要临时认证的URL。 –

+0

您可以从您的应用程序加载文件并将其提供给用户。你不需要一个签名的URL。 –

回答

1

退房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': '[email protected]', 
       'Expires': str(expiration), 
       'Signature': signature} 

# Return the built URL. 
return '{endpoint}{resource}?{querystring}'.format(
    endpoint=self.API_ACCESS_ENDPOINT, resource=resource, 
    querystring=urllib.urlencode(query_params)) 
+0

谷歌应用程序引擎python是否有这样的东西? gcloud似乎有太多开销? –

+0

我只是有点想到这个 - 错误是“ImportError:No module named OpenSSL” - 但是你只使用加密转换p12到pem键,所以我只是离线生成我的pem密钥并将其上传到应用引擎。所以我应该能够消除这些依赖关系 –

5

这里是如何做到这一点围棋:

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 
} 
3

我碰到这个问题就最近也发现了解决内GAE为此在使用Python中内置的服务帐户。使用在google.appengine.api.app_identitysign_blob()函数签署签名字符串,并使用get_service_account_name()在同一封装内获得了GoogleAccessId值。

不知道为什么这是如此糟糕的记录,即使现在知道这个工程我不能找到任何提示使用谷歌搜索,应该可以使用内置帐户用于此目的。非常好,但它的工作原理!

+1

非常感谢。这很好,没有pycrypto。即使在SDK上。 – voscausa

+1

而我的代码在这里:http://stackoverflow.com/questions/29847759/cloud-storage-and-secure-download-strategy-on-app-engine-gcs-acl-or-blobstore – voscausa

0

我不知道为什么the docs是如此糟糕。 SO上唯一的另一个comprehensive answer是伟大而乏味的。

输入generate_signed_url method。爬下兔子洞,你会发现使用这种方法时的代码路径与上述SO帖子中的解决方案在GAE上执行时相同。然而,这种方法不那么单调乏味,支持其他环境,并且具有更好的错误消息。

在代码:

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 
相关问题