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

HttpURLConnection PUT для Google Cloud Storage, дающий ошибку 403

Я попытался загрузить файл в Google Cloud Storage с помощью XML API. У меня есть правильный GoogleAccessId, дата истечения срока действия и подпись, сгенерированная для каждой загрузки. Странно, что я могу PUT файл использовать Postman (приложение для Chrome), поэтому я уверен, что URL-адрес в порядке. Я просто не могу использовать его с помощью моей программы Android Java (она возвращает мне ошибку 403). Исходный код, выполняющий загрузку, находится здесь (он основывается на этом: https://cloud.google.com/storage/docs/access-control#Signing-Strings):

    URL url;
    HttpURLConnection connection;

    try {
        url = new URL("http://google-testbucket.storage.googleapis.com/[email protected]unt.com&Expires=1331155464&Signature=BClz9e4UA2MRRDX62TPd8sNpUCxVsqUDG3YGPWvPcwN%2BmWBPqwgUYcOSszCPlgWREeF7oPGowkeKk7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9sFpqXsQI8IQi1493mw%3D");
        connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");

        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
        out.write("Test");
        out.close();

        Log.i("TAG", "PUT Response code: " + connection.getResponseCode());

    } catch (MalformedURLException e) {
        e.printStackTrace();
        Log.e("TAG", "MalformedURLException");
    } catch (ProtocolException e) {
        e.printStackTrace();
        Log.e("TAG", "ProtocolException");
    } catch (IOException e) {
        e.printStackTrace();
        Log.e("TAG", "IOException");
    }

Документация для объекта PUT: https://cloud.google.com/storage/docs/xml-api/put-object-upload

Может кто-нибудь заглянуть в эту проблему и дать мне подсказки, что могло бы пойти не так с этим?

4b9b3361

Ответ 1

Я только что понял, что HttpURLConnection добавляет заголовок Content-Type со значением application/x-www-form-urlencoded сам по себе. Я сделал это, используя HTTP-сниффер на моем эмуляторе Android.

Этот заголовок с автоматическим добавлением вызвал несоответствие подписи. После того, как я изменил код на стороне сервера, чтобы разрешить запросы с помощью Content-Type: application/x-www-form-urlencoded, он генерирует правильную подпись и отлично работает.

Спасибо @morpheus05 за ваше обязательство.

Ответ 2

Пожалуйста, установите ваш Content-Type следующим образом.

connection.setRequestProperty("Content-Type"," ");

Потому что HttpsUrlConnection автоматически генерирует Content-Type как

"Content-Type: application/x-www-form-urlencoded"

это приведет к несоответствию подписи.