Google云端存储已签名网址 - SignatureDoesNotMatch

时间:2013-12-21 01:09:50

标签: php google-api google-cloud-storage

我能够使用google-api-php-client将文件(image.png)放到我的Google云端存储桶中,但现在我无法尝试创建已签名的网址来访问我的文件网站。示例代码:

$bucketName = 'bucket-name';
$id = 'image.png';
$serviceAccountName = '123456789-xxxx@developer.gserviceaccount.com';
$privateKey = file_get_contents($location_to_key_file);
$signer = new \Google_P12Signer($privateKey, "notasecret");
$ttl = time() + 3600;
$stringToSign = "GET\n" . "\n" . "\n" . $ttl . "\n". '/' . $bucketName . '/' . $id;
$signature = $signer->sign(utf8_encode($stringToSign));
$finalSignature = \Google_Utils::urlSafeB64Encode($signature);
$host = "https://".$bucketName.".storage.googleapis.com";
echo  $host. "/".$id."?GoogleAccessId=" . $serviceAccountName . "&Expires=" . $ttl . "&Signature=" . $finalSignature;

返回:

<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 1387590477 /bucketname/image.png</StringToSign></Error>

即时通讯使用google-api-php-client和php 5.5

我已经举了几个例子:

https://groups.google.com/forum/#!topic/gs-discussion/EjPRAWbWKbw

https://groups.google.com/forum/#!msg/google-api-php-client/jaRYDWdpteQ/xbNTLfDhUggJ

也许配置值我没有正确传递? 我假设应该使用服务帐户电子邮件。还尝试在$ stringToSign中包含md5hash和content-type,结果相同。

任何帮助/提示将不胜感激。

4 个答案:

答案 0 :(得分:4)

rdb几乎为我做了伎俩。我使用working python example from GoogleCloudPlatform进行python以调试url的错误并找到以下内容:

  • GoogleAccessId必须是urlencoded
  • 您必须在签名中替换以下字符:&#39; - &#39; =&GT; &#39;%2B&#39;,&#39; _&#39; =&GT; &#39;%2F
  • 签名必须以&#39;%3D&#39;
  • 结尾

代码:

$host. "/".$id."?Expires=" . $ttl . "&GoogleAccessId=" . 
        urlencode($serviceAccountName) . "&Signature=" . 
        str_replace(array('-','_',), array('%2B', '%2F'),urlencode($finalSignature)).'%3D';

现在网址应该可以使用,您可以使用一些advanced operators like response-content-disposition or response-content-type

答案 1 :(得分:0)

您可以尝试使用$host作为 -

构建签名网址吗?

$host = "https://".$bucketName.".commondatastorage.googleapis.com";

我发现你所指的doc有一点不同。

由于

答案 2 :(得分:0)

你可以试试这个代码:)

$finalSignature = base64_encode($signature);
echo $host. "/".$id."?GoogleAccessId=" . $serviceAccountName . "&Expires=" . $ttl . "&Signature=" . urlencode($finalSignature);

答案 3 :(得分:0)

我认为您的错误位于$finalSignature = \Google_Utils::urlSafeB64Encode($signature);行。这个方法对URL做了一些奇怪的事情并替换了某些字符。

最后,我使用以下代码完成了所有工作:

$expires = time() + 60 * 30; // Half an hour

// Get the key from the key file
$privateKeyPath = Config::get('gcs.signing.key');
$privateKey = file_get_contents($privateKeyPath);
$signer = new Google_Signer_P12($privateKey, Config::get('gcs.signing.password'));

//Signing does not like spaces, however it also doesn't like urlencoding or html entities
$cloudStoragePath = str_replace(' ', '%20', $cloudStoragePath);

//Create string to sign
$stringToSign = "GET\n\n\n" . $expires . "\n" . "/" . $cloudStoragePath;

//Sign
$signature = $signer->sign(utf8_encode($stringToSign));

$query = array(
    'GoogleAccessId' => Config::get('gcs.signing.service_account'),
    'Expires' => $expires,
    'Signature' => base64_encode($signature)
);

$url = self::$storageBaseUrl . '/' . $cloudStoragePath . '?' . http_build_query($query);