亚马逊 S3,GET 请求被禁止?
Amazon S3, GET request forbidden?
我正在构建一个使用 Multer-s3 上传到亚马逊存储桶的 MEAN 堆栈应用程序。
它似乎可以完美地将图像上传到 Amazon-S3 中的存储桶以及数据库,但是当尝试从亚马逊获取图像时(使用 ng-repeat)它会出现以下错误:
GET https://s3-us-west-2.amazonaws.com/bucketfolder/bucketname/b40c4240-0417-11e6-9944-2d167e625d2b.jpg 403 (Forbidden)
在我的主控制器中:
function mainController(Upload, API, S3_BUCKET, TokenService, User, $timeout) {
var self = this;
self.usersClothing = [];
self.uploadSingle = function() {
Upload.upload({
url: API + '/upload/single',
data: { file: self.file, type: self.clothingType }
})
.then(function(res) {
self.usersClothing = res.data.user.clothing.map(function(clothing) {
clothing.image = S3_BUCKET + clothing.image;
return clothing;
});
})
.catch(function(err) {
console.error(err);
});
}
我的 Angular 我上传图片的状态:
<div ng-repeat="clothing in main.usersClothing">
<img ng-src="{{clothing.image}}" class="clothing-img">
</div>
修复了问题:
在我的亚马逊存储桶中,我更改了图像的首选项并将其设置为 public。然后它能够发出 GET 请求。
在您的上传代码片段 (POST
) 中,您的代码正在服务器上执行,并且(我假设,您可以确认)使用 IAM 实例配置文件(角色)或访问密钥来访问您的 S3桶.
但是,您正在将 URL 从服务器传递给您的 S3 对象到客户端(浏览器)。是浏览器向 S3 发出对象的 GET
请求。浏览器没有您的 AWS 凭证。
选项 1
因此,为了让浏览器从 S3 存储桶下载对象,存储桶及其对象需要 public 以便无需身份验证即可下载。
- 授予 "List" 权限 "Everyone"。
- 给你的桶一个策略。
示例存储桶策略:
{
"Version": "2008-10-17",
"Id": "Policy1397495964002",
"Statement": [
{
"Sid": "Stmt123",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucketName/*"
}
]
}
确保更改策略以替换您的真实存储桶名称。
这不需要您更改任何代码。
选项 2(首选)
但是,这意味着您的桶 public 面向世界。为避免这种情况,您应该生成一个预签名的 URL 供客户端使用。使用 s3.getSignedUrl
生成预签名的 URL 并将该 URL 传递给您的客户端以供下载。
这需要对您的服务器端代码进行一些代码更改。
我正在构建一个使用 Multer-s3 上传到亚马逊存储桶的 MEAN 堆栈应用程序。 它似乎可以完美地将图像上传到 Amazon-S3 中的存储桶以及数据库,但是当尝试从亚马逊获取图像时(使用 ng-repeat)它会出现以下错误:
GET https://s3-us-west-2.amazonaws.com/bucketfolder/bucketname/b40c4240-0417-11e6-9944-2d167e625d2b.jpg 403 (Forbidden)
在我的主控制器中:
function mainController(Upload, API, S3_BUCKET, TokenService, User, $timeout) {
var self = this;
self.usersClothing = [];
self.uploadSingle = function() {
Upload.upload({
url: API + '/upload/single',
data: { file: self.file, type: self.clothingType }
})
.then(function(res) {
self.usersClothing = res.data.user.clothing.map(function(clothing) {
clothing.image = S3_BUCKET + clothing.image;
return clothing;
});
})
.catch(function(err) {
console.error(err);
});
}
我的 Angular 我上传图片的状态:
<div ng-repeat="clothing in main.usersClothing">
<img ng-src="{{clothing.image}}" class="clothing-img">
</div>
修复了问题: 在我的亚马逊存储桶中,我更改了图像的首选项并将其设置为 public。然后它能够发出 GET 请求。
在您的上传代码片段 (POST
) 中,您的代码正在服务器上执行,并且(我假设,您可以确认)使用 IAM 实例配置文件(角色)或访问密钥来访问您的 S3桶.
但是,您正在将 URL 从服务器传递给您的 S3 对象到客户端(浏览器)。是浏览器向 S3 发出对象的 GET
请求。浏览器没有您的 AWS 凭证。
选项 1
因此,为了让浏览器从 S3 存储桶下载对象,存储桶及其对象需要 public 以便无需身份验证即可下载。
- 授予 "List" 权限 "Everyone"。
- 给你的桶一个策略。
示例存储桶策略:
{
"Version": "2008-10-17",
"Id": "Policy1397495964002",
"Statement": [
{
"Sid": "Stmt123",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucketName/*"
}
]
}
确保更改策略以替换您的真实存储桶名称。
这不需要您更改任何代码。
选项 2(首选)
但是,这意味着您的桶 public 面向世界。为避免这种情况,您应该生成一个预签名的 URL 供客户端使用。使用 s3.getSignedUrl
生成预签名的 URL 并将该 URL 传递给您的客户端以供下载。
这需要对您的服务器端代码进行一些代码更改。