Google存储区的签名网址与提供的签名不符

时间:2015-07-21 10:06:22

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

我很难使用谷歌存储。

所以我试图制作一个signed url,已经拥有客户端ID(这是一封电子邮件)和私钥(如here所述),所以:

第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 ,搜索后发现google-api-php-client有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最终脚本以便于阅读

所以我知道我做错了什么?

1 个答案:

答案 0 :(得分:3)

我找到了解决方案,我到期的失效日期有一个错误:

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

所以我已将h更改为hours,以便现在可以使用,例如:

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

但是这并没有完全解决它,实际缺失的部分是Google_Signer_P12::sign()要求它在base64上编码,这是在google docs上指定的:

  

Google Cloud Storage期望在其API中使用Base64编码签名。

但是我(错误地)虽然Google_Signer_P12::sign()已经这样做了,所以在我明白它是必需的之后我已经将sign方法更改为:

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

它现在正在工作!!!

我还为想要使用它的人更新了gist:)