SignatureDoesNotMatch与Google的serviceAccounts.signBlob API匹配

时间:2019-06-28 16:25:56

标签: google-cloud-storage google-oauth google-apis-explorer

我正在尝试为存储在Google Cloud Storage(GCS)上的对象生成一个签名URL。

尝试1:使用API​​ Explorer尝试API

为此,我正在尝试按照以下定义对Blob /对象进行签名:

GET


<expiration time>
/<bucket name>/<object/blob name>

我首先尝试了Google的serviceAccounts.signBlob API,如下页所述:

https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signBlob

  

base64编码的字符串。

注意,如上面链接的页面上的API文档所述,我将要签名的Blob的base64表示形式传递给了API。

API的响应具有以下结构,其中包含signedBlob键:

{
  "keyId": "...",
  "signedBlob": "..."
}

然后,我使用获得的签名Blob如下生成签名URL:

encoded_signedBlob = base64.b64encode(signedBlob)
signed_url = "https://storage.googleapis.com/{}/{}?" \
             "GoogleAccessId={}&" \
             "Expires={}&" \
             "Signature={}".format(
    bucket_name, blob_name, 
    service_account_email, 
    expiration, 
    encoded_signedBlob)

,当我将签名的URL粘贴到浏览器中以下载blob时,出现以下错误:

<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>GET <bucket name> <blob/object name></StringToSign>
</Error>

尝试2:尝试使用python库

然后我尝试按以下方法在python中实现它,但仍然遇到相同的错误。

# -------------
# Part 1: obtain access token using the authorization flow discussed at:
# https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials
# -------------
client_service_account = "..."
access_token = build(
    serviceName='iamcredentials',
    version='v1',
    http=http
).projects().serviceAccounts().generateAccessToken(
    name="projects/{}/serviceAccounts/{}".format(
        '-',
        service_account_email),
    body=body
).execute()["accessToken"]

credentials = AccessTokenCredentials(access_token, "MyAgent/1.0", None)

# -------------
# Part 2: sign the blob
# -------------
service = discovery.build('iam', 'v1', credentials=credentials)
name = 'projects/.../serviceAccounts/...'
encoded = base64.b64encode(blob)
sign_blob_request_body = {"bytesToSign": encoded}
request = service.projects().serviceAccounts().signBlob(name=name, body=sign_blob_request_body)
response = request.execute()
keyId = response["keyId"]
signedBlob = response["signature"]


# -------------
# Part 3: generate signed URL
# -------------
encoded_signedBlob = base64.b64encode(signedBlob)
signed_url = "https://storage.googleapis.com/{}/{}?" \
             "GoogleAccessId={}&" \
             "Expires={}&" \
             "Signature={}".format(
    bucket_name, blob_name, 
    service_account_email, 
    expiration, 
    encoded_signedBlob)

1 个答案:

答案 0 :(得分:0)

您可以看一下使用client libraries的实现,可以尝试一下,请记住在您的requirements.txt文件中包含google-cloud-storage和代码中指定的服务帐户python示例