2013-12-21 110 views
1

我可以使用google-api-php-client將文件(image.png)放到我的Google Cloud Storage存儲桶中,但現在我無法嘗試創建簽名url從我的網站訪問該文件。示例代碼:Google Cloud Storage簽署的Url - SignatureDoesNotMatch

$bucketName = 'bucket-name'; 
$id = 'image.png'; 
$serviceAccountName = '[email protected]'; 
$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; 

返回:使用谷歌的API的PHP客戶端使用PHP

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

IM 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,結果相同。

任何幫助/提示,​​將不勝感激。

回答

0

你可以嘗試使用$host作爲構建簽署網址 -

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

有一個區別,我發現與doc你指是。

感謝

+0

相同的結果,改變子域 – rdb

0

你可以試試這個代碼:)

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

RDB中幾乎做的伎倆我。我用python中working python example from GoogleCloudPlatform爲了調試什麼是錯的URL,並找到如下:

  • 的GoogleAccessId已經被url編碼
  • 您在簽名替換下列字符:「 - '=> '%2B', '_'=>' %2F
  • 簽名必須以 '%3D' 端

代碼:

$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

這是對我的答案後。 :-)我忘記了URL編碼也是GoogleAccessId電子郵件地址。謝謝 – flosk8

+1

一旦我得到了正確的簽名(謝謝!)我一直得到一個404響應:「指定的密鑰不存在。」我試圖檢索名稱中包含空格的文件,嵌套了一些「子目錄」。原來我也需要做:'$ id = dirname($ id)。 '/'。 'rawurlencode(basename($ id));'注意兩點:1)你必須使用'rawurlencode()'而不僅僅是'urlencode()'和2)我沒有用空格試過路徑,但是如果你使用rawurlencode ($ id)'那麼你會發送一個以GCS完整路徑命名的文件,這可能不是你想要的。 – jamesvl

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); 
相關問題