如何使用预签名 url 将对象放入 amazon s3?
How do I put object to amazon s3 using presigned url?
我正在尝试使用签名 url 将图像上传到 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);
});
我得到 url。但是当我尝试放置一个对象时,出现以下错误:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>FXXXXXXXXX</RequestId>
<HostId>fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>
更新 1
这是我用户的政策:
{
"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
以下代码有效。现在唯一的问题是签名 url
#!/bin/bash
file=""
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}
您已正确设置存储桶的权限,允许用户访问。
但您还需要编辑用户的策略,以允许用户访问 S3 服务。
编辑您正在使用其凭据生成自签名 URL 的用户的 IAM 策略。此策略允许用户完全管理访问帐户中的所有 S3 存储桶:
{
"Statement": [
{
"Sid": "AllowAllS3Access",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "*"
}
]
}
- 在您的 IAM 控制台中,click Users
- 在右侧列表中,选择您使用的 IAM 用户(应该是 'myuser')
- 在子选项卡上选择权限
- 单击附加策略并选择 AmazonS3FullAccess
最后一页会像 this。
您还可以检查安全凭证子选项卡,您的 accessKeyId 应该在列表中。 secretAccessKey就是拿不到了。
我使用您的代码成功上传了一个文件。
以下是我遵循的步骤:
创建了一个新的存储桶和一个新的 IAM 用户
设置 IAM 用户策略如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1418647210000",
"Effect": "Allow",
"Action": [
"s3:Put*"
],
"Resource": [
"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);
});
复制屏幕上的 URL 并使用 curl 测试上传如下:
curl.exe -k -X PUT -T "someFile" "https://myBucket.s3.amazonaws.com/myKey?AWSAccessKeyId=ACCESS_KEY_ID&Expires=1457632663&Signature=Dhgp40j84yfjBS5v5qSNE4Q6l6U%3D"
在我的情况下,策略更改通常需要 5-10 秒才能生效,因此如果第一次失败,请确保继续发送一段时间。
希望对您有所帮助。
它可能会帮助你:)
添加一个 ContentType 属性 :
s3.getSignedUrl('putObject', {
Bucket: 'myBucket',
Expires: 60*60,
Key: 'myKey',
ContentType: 'image/jpeg',
}, function (err, url) {
console.log(url);
});
这是为 S3 中任何类型的文件生成预签名 URL 的完整代码。
- 如果您愿意,可以在参数中使用 Expire 参数来包含到期时间。
- 下面的代码将上传任何类型的文件,例如 excel(xlsx, pdf, jpeg)
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);
});
});
我正在尝试使用签名 url 将图像上传到 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);
});
我得到 url。但是当我尝试放置一个对象时,出现以下错误:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>FXXXXXXXXX</RequestId>
<HostId>fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>
更新 1
这是我用户的政策:
{
"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
以下代码有效。现在唯一的问题是签名 url
#!/bin/bash
file=""
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}
您已正确设置存储桶的权限,允许用户访问。
但您还需要编辑用户的策略,以允许用户访问 S3 服务。
编辑您正在使用其凭据生成自签名 URL 的用户的 IAM 策略。此策略允许用户完全管理访问帐户中的所有 S3 存储桶:
{
"Statement": [
{
"Sid": "AllowAllS3Access",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "*"
}
]
}
- 在您的 IAM 控制台中,click Users
- 在右侧列表中,选择您使用的 IAM 用户(应该是 'myuser')
- 在子选项卡上选择权限
- 单击附加策略并选择 AmazonS3FullAccess
最后一页会像 this。
您还可以检查安全凭证子选项卡,您的 accessKeyId 应该在列表中。 secretAccessKey就是拿不到了。
我使用您的代码成功上传了一个文件。
以下是我遵循的步骤:
创建了一个新的存储桶和一个新的 IAM 用户
设置 IAM 用户策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1418647210000", "Effect": "Allow", "Action": [ "s3:Put*" ], "Resource": [ "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); });
复制屏幕上的 URL 并使用 curl 测试上传如下:
curl.exe -k -X PUT -T "someFile" "https://myBucket.s3.amazonaws.com/myKey?AWSAccessKeyId=ACCESS_KEY_ID&Expires=1457632663&Signature=Dhgp40j84yfjBS5v5qSNE4Q6l6U%3D"
在我的情况下,策略更改通常需要 5-10 秒才能生效,因此如果第一次失败,请确保继续发送一段时间。
希望对您有所帮助。
它可能会帮助你:) 添加一个 ContentType 属性 :
s3.getSignedUrl('putObject', {
Bucket: 'myBucket',
Expires: 60*60,
Key: 'myKey',
ContentType: 'image/jpeg',
}, function (err, url) {
console.log(url);
});
这是为 S3 中任何类型的文件生成预签名 URL 的完整代码。
- 如果您愿意,可以在参数中使用 Expire 参数来包含到期时间。
- 下面的代码将上传任何类型的文件,例如 excel(xlsx, pdf, jpeg)
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);
});
});