通过签名网址将文件PUT到Google云端存储(GCS)

时间:2013-11-10 13:08:29

标签: java google-cloud-storage

我正在尝试使用“已签名的网址”访问/上传文件到Google云端存储(GCS)。

按照https://developers.google.com/storage/docs/accesscontrol#Signing-Strings

上的说明操作

我做了什么:

  • 在Google Cloud Console中注册了“Web应用程序”。
  • 使用已注册的Web应用程序屏幕的“证书”部分中的“生成新密钥”生成新的私钥。
  • 创建要签名的字符串,并使用页面“如何签名”部分提供的示例代码对其进行签名(只需对Java主程序的硬编码值进行微调)。更新:为GcsSigner.java创建了一个要点。
  • 确保已签名的字符串是URL编码。
  • 指定的HTTP标头:x-goog-api-version,x-goog-project-id,Content-Type。
  • 指定的网址参数:GoogleAccessId,签名,过期。
  • 使用Postman(Chrome扩展程序)模拟PUT请求。

然而,我仍然得到这个(状态:403禁止):

<?xml version='1.0' encoding='UTF-8'?>
<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>PUT

text/plain
1384084959392
x-goog-api-version:2
x-goog-project-id:99999
/mybucket/myfile.txt</StringToSign>
</Error>

即使我根据“StringToSign”中的值对字符串进行重试,我仍然会遇到同样的错误。

在此处阅读各种相关帖子,但找不到任何解决方案,其中大部分都是x-goog-api-version:1,而我使用的是版本2.

我缺少什么?任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:8)

最后使用签名网址将PUT文件设置为Google云端存储。这是通过创建一个简单的Java程序来模拟:

  • Server签署&amp;将字符串编码为签名。
  • Uploader作为未经身份验证的用户,仅使用Server提供的签名提交PUT请求。浏览器使用Apache的HTTP客户端库进行模拟。

您可以在此处看到demo app

当我通过Chrome的Postman扩展提交时,我真的不明白为什么它不起作用。

答案 1 :(得分:4)

虽然文档说Content-Type是可选的,但实际上这意味着您must设置了与您的http请求标头对应的正确content-Type

在这种情况下,您必须在签名字符串中添加content-type: text/plain

https://cloud.google.com/storage/docs/access-control/create-signed-urls-program

答案 2 :(得分:2)

我正在努力使用PUT和签名的URL(使用GAE Cloud Endpoints),但这里有两件事需要我做:

  1. 确保您拥有最新的GAE gradle依赖项。自动生成的但是android studio并不总是最新的。
  2. 对于PUT,你需要让你的字符串符号如下:

    字符串url_signature = sign(动词+&#34; \ n&#34; + contentMD5 +&#34; \ n&#34; + contentType +&#34; \ n&#34; + expiration +&#34; \ n&#34; +&#34; /&#34; + BUCKET_NAME +&#34; /&#34; + objectName);

  3. 如此处所述:https://cloud.google.com/storage/docs/access-control/signed-urls格式为:

    StringToSign = HTTP_Verb + "\n" +
                   Content_MD5 + "\n" +
                   Content_Type + "\n" +
                   Expiration + "\n" +
                   Canonicalized_Extension_Headers +
                   Canonicalized_Resource
    

    那些回归&#34; \ n&#34;是重要的。如果你有太多或不够,你会得到那个错误。例如,如果您没有传递contentMD5,只需传入一个空字符串,这样您就可以获得正确的返回次数&#34; \ n&#34;

答案 3 :(得分:1)

在查看您的代码时,您可以通过省略以下标题来尝试创建 stringToSign -

"x-goog-api-version:2\n" +
"x-goog-project-id:1234\n" +

如下图所示 -

 String stringToSign = "PUT\n" +
                "\n" +
                "text/plain\n" +
                "1384084959392\n" +
                "/test-bucket/bob.txt";

现在尝试生成Sign URL。

由于

答案 4 :(得分:1)

要从浏览器运行已签名的网址,您必须设置HTTP标头。 在https://developers.google.com/storage/docs/accesscontrol#Construct-the-String

Content_Type可选。如果您提供此值,则客户端(浏览器)必须将此HTTP标头设置为相同的值。有一个单词必须

因此,如果您要为符号字符串提供Content_Type,则必须在浏览器http标头中提供相同的Content_Type。当我在浏览器标题中设置Content_Type时,我也可以运行相同的问题,我可以下载文档。