Мне трудно работать с хранилищем Google.
Поэтому я пытаюсь сделать подписанный URL-адрес , уже имею идентификатор клиента (который является адресом электронной почты) и закрытый ключ (как описано здесь ), поэтому:
ШАГ 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. Подписывая строку Initialy, я использовал 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 "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>
Я добавил сущность с окончательным сценарием, чтобы было легче читать
Итак, любая идея, что я делаю неправильно?
Я нашел решение, была ошибка с датой истечения срока действия, в которой я делал:
$expiration = (new DateTime())->modify('+3h')->getTimestamp();
Поэтому я изменил h
на hours
так что теперь он работает, например:
$expiration = (new DateTime())->modify('+3hours')->getTimestamp();
Но это не совсем решило, фактическая недостающая часть заключается в том, что для параметра Google_Signer_P12::sign()
требуется, чтобы он был закодирован на base64, который указан в документах google:
Google Cloud Storage ожидает кодировку Base64 в своих API.
Однако я (ошибочно), хотя Google_Signer_P12::sign()
уже сделал бы это, поэтому, когда я понял, что это необходимо, я изменил метод знака на:
function googleSignString($certificatePath, $stringToSign) { return base64_encode((new Google_Signer_P12( file_get_contents($certificatePath), 'notasecret' ))->sign($stringToSign)); }
И он работает сейчас !!!
Я также обновил суть для всех, кто хочет ее использовать 🙂