2015-07-21 58 views
3

我很難與谷歌存儲合作。Google存儲桶的簽名網址與提供的簽名不符

所以我想做一個signed url,已經有客戶端ID(這是電子郵件)和私鑰(如描述here)這樣:

STEP 1:construct the string

function googleBuildConfigurationString($method, $expiration, $file, array $options = []) { 
    $allowedMethods = ['GET', 'HEAD', 'PUT', 'DELETE']; 

    // initialize 
    $method = strtoupper($method); 
    $contentType = $options['Content_Type']; 
    $contentMd5 = $options['Content_MD5'] ? base64_encode($options['Content_MD5']) : ''; 
    $headers = $options['Canonicalized_Extension_Headers'] ? $options['Canonicalized_Extension_Headers'] . PHP_EOL : ''; 
    $file = $file ? $file : $options['Canonicalized_Resource']; 

    // validate 
    if(array_search($method, $allowedMethods) === false) { 
     throw new RuntimeException("Method '{$method}' is not allowed"); 
    } 
    if(!$expiration) { 
     throw new RuntimeException("An expiration date should be provided."); 
    } 

    return <<<TXT 
    {$method} 
    {$contentMd5} 
    {$contentType} 
    {$expiration} 
    {$headers}{$file} 
    TXT; 
} 

到目前爲止這麼好(我認爲),迴應輸出它看起來類似的例子,所以現在簽署字符串

第2步:signing the string 最初我使用openssl_public_encrypt,周圍搜索後發現,谷歌的API的PHP客戶端具有Google_Signer_P12(其中實際使用openssl_sign),因此該方法是這樣的:

function googleSignString($certificatePath, $stringToSign) { 
    return (new Google_Signer_P12(
     file_get_contents($certificatePath), 
     'notasecret' 
    ))->sign($stringToSign); 
} 

在這裏,我不知道,如果這正確簽署它,終於建立最終網址

第3步:building the URL

function googleBuildSignedUrl($serviceEmail, $file, $expiration, $signature) { 
    return "http://storage.googleapis.com{$file}" 
    . "?GoogleAccessId={$serviceEmail}" 
    . "&Expires={$expiration}" 
    . "&Signature=" . urlencode($signature); 
} 

但在瀏覽器中打開URL將檢索:

<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 1437470250 /example/video.mp4</StringToSign> 
</Error> 

我添加了一個gist與最終腳本更易於閱讀

所以任何想法,我究竟做錯了什麼?

回答

3

我已經找到了解決辦法,有上的失效日期,我是做了一個錯誤:

$expiration = (new DateTime())->modify('+3h')->getTimestamp(); 

所以我改變hhours讓現在的工作,如:

$expiration = (new DateTime())->modify('+3hours')->getTimestamp(); 

但是,這並沒有完全解決它,實際缺少的部分是,Google_Signer_P12::sign()需要它的base64,這是對谷歌文檔指定編碼:

Google Cloud Storage希望在其API中使用Base64編碼簽名。

不過我(錯誤地)雖然這Google_Signer_P12::sign()已經將做到這一點,所以在我理解,這是需要我改變的標誌方法:

function googleSignString($certificatePath, $stringToSign) 
{ 
    return base64_encode((new Google_Signer_P12(
    file_get_contents($certificatePath), 
    'notasecret' 
))->sign($stringToSign)); 
} 

,現在是工作! !

我還更新了gist對於希望使用它:)

+0

我遇到麻煩頭正常工作的人。每當我嘗試添加簽名時,我都會收到簽名錯誤。你介意給你一個在你的答案中添加標題的例子嗎? – bryan

+0

如果你看看[Sign Urls#Construct-the-String](https://cloud.google。com/storage/docs/access-control?hl = en#構建字符串) 它有我的頭文件('$ headers')與* Canonicalized_Extension_Headers *匹配的解釋。有幾個例子。 標頭是可選的,如果您需要檢查可能需要發送的特定標頭,則可能需要這些標頭。 – mloureiro

相關問題