谷歌存储桶的签名URL与提供的签名不匹配

编程入门 行业动态 更新时间:2024-10-13 06:18:58
本文介绍了谷歌存储桶的签名URL与提供的签名不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我在使用Google存储方面遇到了困难.

所以我正在尝试制作一个签名的网址,已经具有客户端ID(即电子邮件)和私钥(如此处所述) ),这样:

步骤1:构造字符串

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:对字符串进行签名 最初,我使用 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); }

在这里,我不确定这是否正确签名,最后建立最终的URL

步骤3:构建URL

function googleBuildSignedUrl($serviceEmail, $file, $expiration, $signature) { return "storage.googleapis{$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>

我添加了要点,其最终脚本更易于阅读

那么你知道我在做什么错吗?

解决方案

我找到了解决方案,我做的到期日期存在一个错误:

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

因此,我将h更改为hours,以便它现在可以正常工作,例如:

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

但是并没有完全解决它,实际缺少的部分是Google_Signer_P12::sign()要求它必须在base64上进行编码,这是在google文档中指定的:

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)); }

现在正在工作!!

我还为想要使用它的任何人更新了要点:

I'm having an hard time working with google storage.

So I'm trying to make a signed url, already have the client id (which is an email) and private key (as described here) so:

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

So far so good (I think), echoing the output it looks similar to the examples, so now to sign the string

STEP 2: signing the string Initialy I was using openssl_public_encrypt, after searching around found that google-api-php-client has the Google_Signer_P12 (which actually uses openssl_sign), so the method looks like:

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

And here I'm not sure if this is signing it correctly, finally building final url

STEP 3: building the URL

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

But the opening the URL in the browser will retrieve:

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

I've added a gist with the final script to be easier to read

So any idea what am I doing wrong?

解决方案

I've found the solution, there was a bug on the expiration date where I was doing:

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

So I've changed h to hours so that it works now, like:

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

But that didn't quite solved it, the actual missing part is that the Google_Signer_P12::sign() requires it to be encoded on base64, which is specified on the google docs:

Google Cloud Storage expects the Base64 encoded signature in its APIs.

However I (wrongly) though that Google_Signer_P12::sign() already would do that, so after I understood that it was required I've changed the sign method to:

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

And it is working now!!!

I've also updated the gist for anyone that wants to use it :)

更多推荐

谷歌存储桶的签名URL与提供的签名不匹配

本文发布于:2023-11-15 14:21:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1595204.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:不匹配   URL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!