【问题标题】:AWS signed URLs working everywhere except AndroidAWS 签名的 URL 可在除 Android 之外的任何地方使用
【发布时间】:2016-04-04 23:30:46
【问题描述】:

我正在使用 AWS Lambda 为我的移动产品创建一个简单的上传服务。

在服务器上,我使用以下代码生成一个预签名 URL

var params = {
    Bucket: targetS3Bucket,
    Key: key,
    Body: '',
    ContentType: event.contentType,
    Expires: 60
};

s3.getSignedUrl('putObject', params, function (err, url){
    context.done(null, {
        'oneTimeUploadUrl': url,
        'resultUrl': urlPrefix + key
    });
});

targetS3Bucket 是 S3 上文件夹的路径,key 是文件本身的名称,urlPrefix 是 S3 上文件的 HTTP 位置的根(即:s3.amazonaws.com/some-folder/

将此代码与内置 HTTP 库一起使用(也就是说,不使用任何 aws SDK)可以在 PC 和 iOS 上正常运行,但在 Android 上则不行。

最新版本的 Android 客户端代码如下所示:

uri = new URL(oneTimeUploadUrl);

// Setup Connection
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection();
http.setDoOutput(true);
http.setRequestMethod("PUT");
​
// Write Data
OutputStream os = http.getOutputStream();
os.write(_bytes);
os.flush();
os.close(); // request gets sent off to the server

这始终失败,代码为400。我尝试了几件事,比如更改编码、使用HttpsURLConnection 的非 https 版本以及其他一些事情,但无济于事。

我宁愿避免引入 AWS 开发工具包,因为我只需要这个单一功能即可工作,并且使用这个 Lambada 端解决方案可以在除 android 之外的所有平台上实现这一点。

这是从 AWS 返回的 XML。返回的消息令人困惑,因为客户端从不更改令牌,并且相同的过程在其他设备上成功。

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidToken</Code>
    <Message>The provided token is malformed or otherwise invalid.</Message>
    <Token-0>{Token-0}</Token-0>
    <RequestId>{RequestId}</RequestId>
    <HostId>{HostId}</HostId>
</Error>

【问题讨论】:

  • 你能捕捉到伴随400 Bad Request响应的响应正文吗?应该有一些带有提示的人类可读的 XML 来帮助我们弄清楚具体发生了什么。否则,这只是猜测。
  • 用此信息更新了主要评论
  • 感谢您的更新。我怀疑,我们需要用更少的编辑来看待事情。预签名 URL 中的任何内容或错误响应都不是真正敏感的 - RequestId 和 HostId 只是 AWS 支持人员可以用来研究其日志中的错误的值,因此不需要显示这些值(但不敏感),如果你想删除 accesskeyid(通常以 A*IA 开头),你可以从 URL 中删除它......但我们可能需要查看 URL 的其余部分和响应。

标签: java android amazon-web-services aws-lambda


【解决方案1】:

问题是HttpURLConnection 默默地将Content-Type: application/x-www-form-urlencoded 添加到请求中。这很烦人,因为很难确定 HttpURLConnection 对象的请求中包含哪些标头。

无论如何。这是正确的代码

uri = new URL(oneTimeUploadUrl);

// Setup Connection
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection();
http.setDoOutput(true);
http.setRequestMethod("PUT");
http.setRequestProperty("Content-Type"," "); // remove Content-Type header

// Write Data
OutputStream os = http.getOutputStream();
os.write(_bytes);
os.flush();
os.close(); // request gets sent off to the server

另请参阅:HttpURLConnection PUT to Google Cloud Storage giving error 403

【讨论】:

    猜你喜欢
    • 2022-07-03
    • 2012-11-24
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2017-09-21
    • 2015-08-10
    • 1970-01-01
    相关资源
    最近更新 更多