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.
Что мне не хватает? Любая помощь будет принята с благодарностью.
Ответы
Ответ 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"