Подтвердить что ты не робот

PUT файлы в облачное хранилище Google (GCS) с помощью подписанных URL-адресов

Я пытаюсь использовать "подписанные URL" для доступа/загрузки файлов в облачное хранилище Google (GCS).

Следуйте инструкциям в https://developers.google.com/storage/docs/accesscontrol#Signing-Strings

Что я сделал:

  • Зарегистрировано "Веб-приложение" на Google Cloud Console.
  • Сгенерированный новый закрытый ключ с использованием "Создать новый ключ" в разделе "Сертификат" на экране зарегистрированного веб-приложения.
  • Создал мою строку, которая будет подписана и подпишут ее, используя пример кода, предоставленного в разделе "Как подписать" на странице (только незначительные изменения в значениях жесткого кода для основной программы Java). Обновление: Создал сущность для GcsSigner.java.
  • Убедитесь, что подписанная строка закодирована в URL.
  • HTTP-заголовки указаны: x-goog-api-версия, x-goog-project-id, Content-Type.
  • Параметры URL, указанные: GoogleAccessId, подпись, срок действия.
  • Используйте Postman (расширение Chrome) для имитации запроса PUT.

Однако я все еще получаю это (статус: 403 Запрещено):

<?xml version='1.0' encoding='UTF-8'?>
<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>PUT

text/plain
1384084959392
x-goog-api-version:2
x-goog-project-id:99999
/mybucket/myfile.txt</StringToSign>
</Error>

Даже когда я повторяю, подписывая строку на основе значений в "StringToSign", я все равно получаю ту же ошибку.

Прочитайте здесь различные связанные записи, но не смогли найти решение, и большинство из них относится к x-goog-api-version:1, в то время как я использую версию 2.

Что мне не хватает? Любая помощь будет принята с благодарностью.

4b9b3361

Ответ 1

Наконец удалось загрузить файлы в Google Cloud Storage с помощью подписанных URL-адресов. Это было сделано путем создания простой Java-программы для имитации:

  • Server, чтобы подписать и закодировать строку как подпись.
  • Uploader, поскольку пользователь, не прошедший проверку подлинности, отправляет запрос PUT, используя только подпись, предоставленную Server. Браузер моделируется с использованием Apache HTTP Client library.

Здесь вы можете увидеть демонстрационное приложение .

Я не понимаю, почему это не сработало, когда я отправил через расширение Chrome Postman.

Ответ 2

Хотя документ говорит, что Content-Type является необязательным, это на самом деле означает, что вы must установите правильный Content-Type, соответствующий вашему заголовку HTTP-запроса.

В этом случае ваш должен добавить content-type: text/plain в строку подписи.

https://cloud.google.com/storage/docs/access-control/create-signed-urls-program

Ответ 3

Изучив свой код, попробуйте создать stringToSign, опуская следующие заголовки -

"x-goog-api-version:2\n" +
"x-goog-project-id:1234\n" +

Как показано ниже -

 String stringToSign = "PUT\n" +
                "\n" +
                "text/plain\n" +
                "1384084959392\n" +
                "/test-bucket/bob.txt";

Теперь попробуйте создать Sign Sign.

Спасибо

Ответ 4

Чтобы запустить положенный URL из браузера, вы должны установить HTTP-заголовок. В https://developers.google.com/storage/docs/accesscontrol#Construct-the-String

Content_Type Необязательный. Если вы укажете это значение, клиент (браузер) должен предоставить этому HTTP-заголовку значение, равное одному значению. Существует слово must

Итак, если вы предоставляете Content_Type для строки знака, вы должны указать тот же Content_Type в http-заголовке браузера. Я также работал с той же проблемой, когда я установил Content_Type в заголовок браузера, я смог загрузить документ.

Ответ 5

Я боролся с PUT и подписанным URL (с конечными точками GAE Cloud), но вот две вещи, которые мне нужно было сделать:

  • Убедитесь, что у вас есть последние зависимости GAE gradle. Автоматически созданные, но андроид-студии не всегда являются последними.
  • Для PUT вам нужно, чтобы ваша строка была подписана так:

    String url_signature = sign (verb + "\n" + contentMD5 + "\n" + contentType + "\n" + expiration + "\n" + "/" + BUCKET_NAME + "/" + objectName);

Как объясняется здесь: https://cloud.google.com/storage/docs/access-control/signed-urls формат:

StringToSign = HTTP_Verb + "\n" +
               Content_MD5 + "\n" +
               Content_Type + "\n" +
               Expiration + "\n" +
               Canonicalized_Extension_Headers + "\n" +
               Canonicalized_Resource

Те, кто возвращает "\n" , важны. Если у вас слишком много или недостаточно, вы получите эту ошибку. Если вы не передаете ContentMD5, например, просто передайте пустую строку, чтобы получить правильный номер возврата "\n"