HttpURLConnection PUT 到谷歌云存储给出错误 403

我尝试使用 XML API 将文件上传到 Google Cloud Storage.我为每次上传生成了正确的 GoogleAccessId、到期日期和签名.奇怪的是,我可以使用 Postman(Chrome 应用程序)PUT 文件,所以我确定 URL 没问题.我只是无法使用我的 Android Java 程序放置它(它返回给我 403 错误).执行上传的源代码在这里(它基于这个:https://cloud.google.com/storage/docs/access-control#Signing-Strings):

I tried to upload a file to Google Cloud Storage using XML API. I have the right GoogleAccessId, expiry date and signature generated for each upload. The strange thing is that I can PUT file using Postman (application for Chrome), so I'm sure that the URL is ok. I just cannot PUT it using my Android Java program (it returns to me 403 error). The source code performing upload is here (it base on this one: https://cloud.google.com/storage/docs/access-control#Signing-Strings):

    URL url;
    HttpURLConnection connection;

    try {
        url = new URL("http://google-testbucket.storage.googleapis.com/testdata.txt?GoogleAccessId=1234567890123@developer.gserviceaccount.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

任何人都可以调查这个问题并给我提示这个问题可能出了什么问题吗?

Can anybody look into this problem and give me hints what might went wrong with this one?

推荐答案

我刚刚发现 HttpURLConnection 添加了 Content-Type 标头,其值为 application/x-www-form-urlencoded 本身.我已经在我的 android 模拟器上使用 HTTP 嗅探器完成了它.

I just figured out that HttpURLConnection adds Content-Type header with value application/x-www-form-urlencoded by itself. I've done it using HTTP sniffer on my android emulator.

此自动添加的标头导致签名不匹配.在我更改服务器端的代码以允许使用 Content-Type: application/x-www-form-urlencoded 的请求后,它会生成正确的签名并且工作正常.

This auto-added header caused signature mismatch. After I changed the code on the server-side to allow requests with Content-Type: application/x-www-form-urlencoded it generates the right signature and it works fine.

感谢@morpheus05 的承诺.

Thank you @morpheus05 for your commitment.

相关文章