flo*_*olu 3 acl amazon-s3 amazon-web-services node.js aws-sdk
我正在使用NodeJs将文件上传到AWS S3。我希望客户端能够安全地下载文件。因此,我正在尝试生成签名的URL,这些URL在一次使用后会过期。我的代码如下所示:
上载中
const s3bucket = new AWS.S3({
accessKeyId: 'my-access-key-id',
secretAccessKey: 'my-secret-access-key',
Bucket: 'my-bucket-name',
})
const uploadParams = {
Body: file.data,
Bucket: 'my-bucket-name',
ContentType: file.mimetype,
Key: `files/${file.name}`,
}
s3bucket.upload(uploadParams, function (err, data) {
// ...
})
Run Code Online (Sandbox Code Playgroud)
正在下载
const url = s3bucket.getSignedUrl('getObject', {
Bucket: 'my-bucket-name',
Key: 'file-key',
Expires: 300,
})
Run Code Online (Sandbox Code Playgroud)
问题
打开URL时,我得到以下信息:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>
There were headers present in the request which were not signed
</Message>
<HeadersNotSigned>host</HeadersNotSigned>
<RequestId>D63C8ED4CD8F4E5F</RequestId>
<HostId>
9M0r2M3XkRU0JLn7cv5QN3S34G8mYZEy/v16c6JFRZSzDBa2UXaMLkHoyuN7YIt/LCPNnpQLmF4=
</HostId>
</Error>
Run Code Online (Sandbox Code Playgroud)
我完全没有找到错误。我真的很感谢您的帮助:)
Spe*_*ton 44
这里得到最高支持的答案在技术上是可行的,但并不实用,因为它公开了桶。
我遇到了同样的问题,这是由于用于生成签名 url 的角色造成的。我使用的角色是这样的:
- Effect: Allow
Action:
- "s3:ListObjects"
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:PutObject"
Resource:
- "arn:aws:s3:::(bucket-name-here)"
Run Code Online (Sandbox Code Playgroud)
但仅存储桶名称还不够,我必须在末尾添加通配符来指定对整个存储桶的访问:
- Effect: Allow
Action:
- "s3:ListObjects"
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:PutObject"
Resource:
- "arn:aws:s3:::(bucket-name-here)/*"
Run Code Online (Sandbox Code Playgroud)
您的代码正确,请仔细检查以下内容:
您的存储桶访问策略。
您通过API密钥获得的存储桶权限。
您的API密钥和机密。
您的存储桶名称和密钥。
对于存储桶策略,您可以使用以下内容:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket/*"
}
]
}
Run Code Online (Sandbox Code Playgroud)
用您的存储桶名称更改存储桶。
对于用户和访问密钥许可权(#2),应遵循以下步骤:
1-转到AWS Identity and Access Management(IAM),然后单击Policies链接,然后单击“创建策略”按钮。
2-选择JSON选项卡。
3-输入以下语句,确保更改存储桶名称,然后单击“查看策略”按钮。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::YOURBUCKETNAME"
}
]
}
Run Code Online (Sandbox Code Playgroud)
4-输入您的策略名称,然后单击“创建策略”按钮。
5单击“用户”链接,找到您当前的用户名(您已经具有该用户名的访问密钥和机密)
6单击“添加权限”按钮。
7-添加我们在上一步中创建的策略并保存。
最后,确保您的存储桶不可从“公共”访问,将正确的内容类型添加到文件中并进行设置 signatureVersion: 'v4'
最终代码应该是这样的,谢谢@Vaisakh PS:
const s3bucket = new AWS.S3({
signatureVersion: 'v4',
accessKeyId: 'my-access-key-id',
secretAccessKey: 'my-secret-access-key',
Bucket: 'my-bucket-name',
})
const uploadParams = {
Body: file.data,
Bucket: 'my-bucket-name',
ContentType: file.mimetype,
Key: `files/${file.name}`,
}
s3bucket.upload(uploadParams, function (err, data) {
// ...
})
const url = s3bucket.getSignedUrl('getObject', {
Bucket: 'my-bucket-name',
Key: 'file-key',
Expires: 300,
})
Run Code Online (Sandbox Code Playgroud)
小智 5
我也曾在使用无服务器框架的应用程序中遇到过这个问题。
我的修复方法是将 S3 权限添加到 serverless.yml 文件内的 IAM 角色。
我不太确定 s3 如何生成预签名 URL,但事实证明它们会考虑您的 IAM 角色。
添加所有 s3 操作就可以了。这就是 S3 的 IAM 角色
iamRoleStatements:
- Effect: Allow
Action:
- 's3:*'
Resource:
- 'arn:aws:s3:::${self:custom.imageBucket}/*'
Run Code Online (Sandbox Code Playgroud)