【发布时间】:2020-04-22 05:32:36
【问题描述】:
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_ID、AWS_SECRET_ACCESS_KEY)附加了以下政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1418647210000",
"Effect": "Allow",
"Action": [
"s3:Put*"
],
"Resource": [
"arn:aws:s3:::my-actual-bucket-name-here/*"
]
}
]
}
我的实际存储桶没有设置 Bucket policy 并且具有以下 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,
},
});
在我的“网络”选项卡中,我可以看到一个 OPTIONS 请求最终返回 200,以及一个以 403 结尾的后续 PUT 请求:
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>BFBCD6D538B3EB6A</RequestId><HostId>BtQuuVJw63Ixvir1ghCu0QLq/FKORNSIyyIh9AoYhul1TnsaoZZ1V0p/FBooM/0HTNhM7ZSegM8=</HostId></Error>
知道我在这里做错了什么吗?
【问题讨论】:
-
将
s3:GetObject添加到您的 IAM 策略以检查是否可以解决问题。 -
@jweyrich——它确实做到了!为什么会这样?
标签: javascript node.js amazon-web-services amazon-s3