上传到 S3 时如何解决 403 Forbidden 错误
Posted
技术标签:
【中文标题】上传到 S3 时如何解决 403 Forbidden 错误【英文标题】:How to resolve 403 Forbidden error when uploading to S3 【发布时间】:2019-12-09 13:04:07 【问题描述】:我正在建立一个 vuejs / DropzoneJS - 松散地基于 kfei 的 vue-s3-dropzone 应用程序的应用程序。它旨在使用 AWS Lambda 函数和 AWS S3 存储桶无服务器地将文件(通过使用 PUT 方法)上传到 AWS S3。我基本上是在来自源 'http://localhost:8080' 的'https://xxxxxxxxxxxxxxxxxxx' 处获取 XMLHttpRequest 已被阻止通过 CORS 策略:对预检请求的响应未通过访问控制检查:当我尝试将图像上传到 S3 存储桶时,它没有 HTTP ok 状态和 403 错误代码。有什么我可以做的吗
这就是我所做的:
-
创建了一个 S3 存储桶
在 S3 存储桶设置中设置存储桶策略和 CORS 配置:
enter image description here enter image description here
创建了一个 lambda 函数,该函数应该签署一个 URL,该 URL 允许将每个文件的 PUT 上传到 S3,执行 Lambda 的角色在 S3 存储桶上具有 PutObject 和 PutObjectAcl 权限:
enter image description here
使用 OPTIONS 方法(以通过预检检查)和使用这些 CORS 设置的 PUT 方法设置 Api Gateway API:
b. OPTIONS 方法有一个 Mock 后端集成,集成响应返回以下内容:
Access-Control-Allow-Headers 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,x-requested-with' 访问控制允许方法“PUT,OPTIONS” 访问控制允许来源'*'
c。 PUT 方法有:
“访问控制允许来源”:“*”
在 AWS Api Gateway 中:设置 api-key 和使用计划
lambda 代码:
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
var bucketName = process.env.AWS_BUCKET_NAME;
exports.handler = (event, context) =>
if (!event.hasOwnProperty('contentType'))
context.fail( err: 'Missing contentType' );
if (!event.hasOwnProperty('filePath'))
context.fail( err: 'Missing filePath' );
var params =
Bucket: bucketName,
Key: event.filePath,
Expires: 3600,
ContentType: event.contentType
;
s3.getSignedUrl('putObject', params, (err, url) =>
if (err)
context.fail( err );
else
context.succeed( url );
);
;
预期:文件上传成功 实际:可能的 CORS 问题。
【问题讨论】:
如果您看到 403 响应,则 S3 不会提供 cors 标头,您也会看到 cors 错误,问题出在权限上。 【参考方案1】:getSignedUrl 如果您从 Postman 或 Node.js 服务器等 API 客户端上传文件,则可以正常工作,但正如您所说,您看到预检检查失败,我假设您正在使用某种 html 表单和前端 js。
来自AWS javascript SDK Docs 关于getSignedUrl:
注意:使用预签名时,并非所有操作参数都受支持 网址。某些参数,例如 SSECustomerKey、ACL、Expires、 发送内容时,必须将 ContentLength 或 Tagging 作为标头提供 要求。 如果您使用预签名 URL 从浏览器上传,并且 需要使用这些字段,请参见 createPresignedPost()。
当您在调用 getSignedUrl 并从浏览器发送时设置“Expires”参数时,您需要在 Lambda 代码中使用 createPresignedPost 而不是 getSignedUrl。
然后您需要从浏览器向 S3 发送 POST 而不是 PUT。
注意:记得使用 POST 更新 S3 的 CORS 规则
【讨论】:
以上是关于上传到 S3 时如何解决 403 Forbidden 错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 AWS CLI 上传到 S3 时如何设置 Content-Type?