Google cloud storage 使用签名URL时Google云服务put失败

Google cloud storage 使用签名URL时Google云服务put失败,google-cloud-storage,Google Cloud Storage,我无法通过签名URL将文件放入google云服务。当我尝试从JS客户端执行PUT时,我得到: “SignatureDesNotMatch…我们计算的请求签名与您提供的签名不匹配。请检查您的Google密钥和签名方法。” 当我尝试使用CURL发布文件时,我得到了相同的错误 我使用的curl命令是: #!/bin/bash URL="https://storage.googleapis.com/..." echo $URL curl $URL -H "Content-Type: image/jpg

我无法通过签名URL将文件放入google云服务。当我尝试从JS客户端执行PUT时,我得到:

“SignatureDesNotMatch…我们计算的请求签名与您提供的签名不匹配。请检查您的Google密钥和签名方法。”

当我尝试使用CURL发布文件时,我得到了相同的错误

我使用的curl命令是:

#!/bin/bash 
URL="https://storage.googleapis.com/..."
echo $URL
curl $URL -H "Content-Type: image/jpg" --upload-file b.jpg
我已经根据文档配置了我打算将数据发布到的bucket,我已经生成了一个带有密钥的服务帐户,该密钥用于生成已签名的url

我签署的申请表如下:

PUT

image/jpg
1234567890
my-bucket/b.jpg
其中设置并计算过期和存储桶名称

我有以下Groovy代码来生成签名URL:

 public String sign(PrivateKey key, String toSign) {
    Signature signer = Signature.getInstance("SHA256withRSA");
    signer.initSign(key);
    signer.update(toSign.getBytes("UTF-8"));
    byte[] rawSignature = signer.sign();
    String s = new String(Base64.encodeBase64(rawSignature), "UTF-8");

    return s;
}

public String signUrl(PrivateKey key, String clientId, String method, String md5, String contentType,
                             long expiration, String gcsPath) {

    String toSign = "${method}\n${md5}\n${contentType}\n${expiration}\n${gcsPath}";
    String signature = sign(key, toSign);
    String url = java.net.URLEncoder.encode(signature);
    return url;
}

public String generateSignedUrl(PrivateKey key, String clientId, String method, String md5, String contentType,
                                       long expiration, String gcsPath) {

    String canonicalizedResource = "/${gcsPath}";
    String signature = signUrl(key, clientId, method, md5, contentType, expiration, canonicalizedResource);
    String finalUrl = "https://storage.googleapis.com/${gcsPath}?GoogleAccessId=${clientId}&Expires=${expiration}&Signature=${signature}"

    finalUrl
}
此代码附带以下直接从gsutils github项目()中提取的通过单元测试:


感谢您提供的任何见解,我已经解决这个问题一段时间了。

调试签名URL逻辑很困难。不过,有一个有用的技巧可以帮助你。您描述的错误响应如下所示:

<?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/jpeg
1472720161
/myBucket/test.txt</StringToSign></Error>
最后一位是关键的。其中的字符串正好是GCS将要签名的字符串,也是您也应该签名的字符串。将您的字符串与此字符串进行比较;在某些方面可能会有所不同


另外,由于实现此签名逻辑很棘手,我建议您使用,而不是自己实现此逻辑。

可能导致此错误的一个原因(以前发生在我身上)是当您使用签名字符串生成base64编码的签名时,编码签名可能包含非法url字符+/。请确保在字符串中分别用%2B%2F替换它们。

我想知道,如果您直接通过“gsutil signurl”命令生成签名URL,它是否仍然失败?嗨,布兰登,非常感谢您的帮助!使用gsutils生成URL会产生另一个错误:
AccessDenied
访问被拒绝。调用者没有storage.objects.create访问bucket my bucket。
Hi Brandon,使服务帐户成为bucket的“所有者”解决了此问题。因此,基本上,我能够使用gsutil和通过curl发布的方式对url进行签名,这太棒了!我也在研究你下面的建议,这需要一点时间。这太棒了!嗨,布兰登,我从来没有发现问题的根源。我切换到了你建议的API,事情似乎好多了。非常感谢。
<?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/jpeg
1472720161
/myBucket/test.txt</StringToSign></Error>