我正在尝试使用已签名的网址将图片上传到s3存储桶。以下是我的存储桶政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::12345678:user/myuser",
"arn:aws:iam::12345678:root"
]
},
"Action": [
"s3:List*",
"s3:Put*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::myBucket",
"arn:aws:s3:::myBucket/*"
]
}
]
}
我正在从服务器生成签名的URL,如下所示:
var aws = require('aws-sdk');
aws.config = {
accessKeyId: myAccessKeyId,
secretAccessKey: mySecretAccessKey
};
var s3 = new aws.s3();
s3.getSignedUrl('putObject', {
Bucket: 'myBucket',
Expires: 60*60,
key: 'myKey'
}, function (err, url) {
console.log(url);
});
我得到了网址。但是当我尝试放置一个对象时,我收到以下错误:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>FXXXXXXXXX</RequestId>
<HostId>fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>
更新1
以下是myuser的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::2xxxxxxxxxxx:user/myuser",
"arn:aws:iam::2xxxxxxxxxxx:root"
]
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::myBucket",
"arn:aws:s3:::myBucket/*"
]
}
]
}
更新2 我只能在设置以下选项时上传。我不明白如果只手动选择权限工作,使用存储桶策略是什么。
更新3
以下代码有效。现在唯一的问题是签名网址
#!/bin/bash
file="$1"
bucket="mybucket"
resource="/${bucket}/${file}"
contentType="image/png"
dateValue=`date -R`
stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
s3Key="AKxxxxxxxxxxxxxxxxx"
s3Secret="/Wuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret} -binary | base64`
curl -X PUT -T "${file}" \
-H "Host: ${bucket}.s3.amazonaws.com" \
-H "Date: ${dateValue}" \
-H "Content-Type: ${contentType}" \
-H "Authorization: AWS ${s3Key}:${signature}" \
https://${bucket}.s3.amazonaws.com/${file}
答案 0 :(得分:12)
我成功地使用您的代码上传了一个文件。
以下是我遵循的步骤:
创建了一个新存储桶和一个新的IAM用户
设置IAM用户的政策如下:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:taskAffinity="com.mypage.app"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mypagemobileapp"/>
<data android:scheme = "http"
android:host="www.mypage.com"/>
</intent-filter>
</activity>
未创建存储桶策略
使用您的代码生成预签名网址:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1418647210000",
"Effect": "Allow",
"Action": [
"s3:Put*"
],
"Resource": [
"arn:aws:s3:::myBucket/*"
]
}
]
}
在屏幕上复制URL并使用curl测试上传,如下所示:
var aws = require('aws-sdk');
aws.config = {
accessKeyId: myAccessKeyId,
secretAccessKey: mySecretAccessKey
};
var s3 = new aws.s3();
s3.getSignedUrl('putObject', {
Bucket: 'myBucket',
Expires: 60*60,
Key: 'myKey'
}, function (err, url) {
console.log(url);
});
在我的情况下,通常需要5-10秒才能使策略更改生效,因此如果第一次失败,请确保继续发送一段时间。
希望这有帮助。
答案 1 :(得分:2)
您已正确设置存储桶的权限,以允许用户进行访问。
但您还需要编辑用户的策略,以允许用户访问S3服务。
编辑您用于生成自签名URL的凭据的用户的IAM策略。这样的事情肯定会涵盖一切:
{
"Statement": [
{
"Sid": "AllowAllS3Access",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "*"
}
]
}
答案 2 :(得分:2)
最后一页将像this。
您还可以查看Security Credentials子选项卡,您的accessKeyId应该在列表中。 secretAccessKey再也无法恢复。
答案 3 :(得分:1)
它也可以帮到你:) 添加 ContentType 属性:
$exe = "C:\$var.exe"
Start-Process $exe -Verb runas
答案 4 :(得分:0)
这是在 S3 中为任何类型的文件生成预签名 URL 的完整代码。
const AWS = require('aws-sdk');
const fs = require('fs');
const axios = require('axios');
const s3 = new AWS.S3();
const filePath = 'C:/Users/siva.cheedella/Downloads/invoice.pdf';
var params = {
Bucket: 'testing-presigned-url-dev',
Key: 'dummy.pdf',
"ContentType": "application/octet-stream"
};
s3.getSignedUrl('putObject', params, function (err, url) {
console.log('The URL is', url);
fs.writeFileSync("./url.txt", url);
axios({
method: "put",
url,
data: fs.readFileSync(filePath),
headers: {
"Content-Type": "application/octet-stream"
}
})
.then((result) => {
console.log('result', result);
}).catch((err) => {
console.log('err', err);
});
});