javascript - S3 预签名 URL 文件上传 – NodeJS + 客户端

标签 javascript node.js amazon-web-services amazon-s3

tl;dr – 从浏览器向从服务器 (AWS S3) 获取的预签名 URL 发出的 OPTIONS 请求获取 200,但以下 PUT 请求获取 403

这是我负责 AWS 及其 S3 服务的服务器端代码:

const AWS = require('aws-sdk');
const config = {
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: process.env.AWS_BUCKET_REGION,
};
AWS.config.update(config);

const S3Bucket = new AWS.S3({
  signatureVersion: 'v4',
  params: { Bucket: process.env.AWS_BUCKET_NAME },
});

const uploadImage = async (fileData) => {
  // fileData contains `name` and `type` properties
  const Key = `images/${fileData.name}`;
  const params = {
    Bucket: process.env.AWS_BUCKET_NAME,
    Key,
    Expires: 15 * 60, // 15 minutes
    ContentType: fileData.type,
    ACL: 'public-read',
  };
  const url = await S3Bucket.getSignedUrlPromise('putObject', params);
  return url;
};

上述代码中的 IAM 用户(AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)附加了以下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1418647210000",
            "Effect": "Allow",
            "Action": [
                "s3:Put*"
            ],
            "Resource": [
                "arn:aws:s3:::my-actual-bucket-name-here/*"
            ]
        }
    ]
}

我的实际存储桶没有设置存储桶策略,并且具有以下 CORS 配置:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

当我从浏览器向服务器发出请求时,我会在响应中收到一个签名 URL。然后我使用此 URL 通过以下代码执行 put 请求:

// `file` is a File class object (that inherits from `FilePrototype` which inherits from `BlobPrototype` that has the following attributes
// lastModified: 1556044130023
​// name: "profile.jpg"
​​// size: 788956
​​// type: "image/jpeg"
​​// uid: "rc-upload-1578069253604-2"
​​// webkitRelativePath: ""

const url = 'https://my-actual-bucket.s3.eu-central-1.amazonaws.com/images/profile.jpg?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MYCREDENTIALCODE%2F20200103%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20200103T163418Z&X-Amz-Expires=900&X-Amz-Signature=b90ed9cbdfadc6401521f80f5d4a65e7d4182becd392ad274ffbe3405d626055&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read';
const response = await fetch(url, {
  method: 'PUT',
  body: file,
  headers: {
    'Content-Type': file.type,
  },
});

在我的“网络”选项卡中,我可以看到最终返回 200OPTIONS 请求,以及最终返回 403 的以下 PUT 请求:

<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>BFBCD6D538B3EB6A</RequestId><HostId>BtQuuVJw63Ixvir1ghCu0QLq/FKORNSIyyIh9AoYhul1TnsaoZZ1V0p/FBooM/0HTNhM7ZSegM8=</HostId></Error>

知道我在这里做错了什么吗?

最佳答案

您需要将 S3:GetObject 权限添加到您的 IAM 策略。需要此权限是因为用户(在本例中为应用程序)最终授予其他人通过预签名 URL“读取”(获取)对象的权限。因此,它还需要具有“读取”(获取)权限。

关于javascript - S3 预签名 URL 文件上传 – NodeJS + 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59582186/

相关文章:

javascript - 如何在cookie中存储计时器值

javascript - jQuery 页面滚动动画只适用于 chrome

javascript - jQuery - 滚动停止上的绑定(bind)事件

node.js - 无法将对象插入 mongoose/mongodb 的数组中?

linux - Elastic Beanstalk : log task customization on Amazon Linux 2 platforms

javascript - typescript :从当前类的另一个方法调用方法

javascript - Node.js 缓冲区和二进制文件

node.js - 如何在 Vue.js 中使用 dotenv

python - ImportError : Could not import settings (Is it on > sys. 路径?设置文件中是否存在导入错误?)在 AWS Elastic Beanstalk 上

amazon-web-services - Cloudformation KeyValuePair 列表作为参数