当前位置: 首页 > 知识库问答 >
问题:

使用预先签名的URL上载到S3 Bucket会出现403禁止的错误

贝钧
2023-03-14

我正在尝试使用预先签名的URL为Vue应用程序实现图片上传功能。第一步是向API发送请求,该API将创建签名URL以上载文件。这部分很好:

服务器端:

'use strict';

const aws = require('aws-sdk');
const config = require('../config');
const util = require('./util');
const uuidv4 = require('uuid/v4');

const bucketName = 'myAmazonS3Bucket';

aws.config.update({
  secretAccessKey: config.AWS_SECRET_ACCESS_KEY,
  accessKeyId: config.AWS_ACCESS_KEY_ID,
  region: 'us-west-2'
});

const s3 = new aws.S3({ signatureVersion: 'v4' });

const handler = async (event) => {
    console.log('Uploading file...');

    return await getUploadURL();
}

const getUploadURL = async () => {
    const actionId = uuidv4();

    const s3Params = {
      Bucket: bucketName,
      Key:  `${actionId}.jpg`,
      ContentType: 'image/jpeg',
      ACL: 'public-read'
    };

    console.log(s3Params);

    return new Promise((resolve, reject) => {
        let uploadURL = s3.getSignedUrl('putObject', s3Params);

        console.log(uploadURL);

        resolve({
            "statusCode": 200,
            "isBase64Encoded": false,
            "headers": { "Access-Control-Allow-Origin": "*" },
            "body": JSON.stringify({
                "uploadURL": uploadURL,
                "photoFilename": `${actionId}.jpg`
            })
        });

        reject({
            "statusCode": 500,
            "headers": { "Access-Control-Allow-Origin": "*" },
            "body": "A funky error occurred and I am not happy about it!"
        })
    });
}

module.exports = {
    handler
}

API终结点发送类似于此的响应:

{
    "uploadURL": "https://s3.us-west-2.amazonaws.com/pics.amazon-clone.io/7925d452-cadd-4f06-ba63-cc50645e3cfb.jpg?AWSAccessKeyId=AKIASGDJJ5ZLUVPMUYMQ&Content-Type=image%2Fjpeg&Expires=1580276753&Signature=3rqNckP4DiL6DkWPRuEGJsuIGpw%3D&x-amz-acl=public-read",
    "photoFilename": "7925d452-cadd-4f06-ba63-cc50645e3cfb.jpg"
}

客户端将使用上传url将文件上传到S3存储桶。以下是客户端代码:

uploadImage: async function (e) {
            console.log('Upload clicked')
            console.log(e)

            // Get the presigned URL
            const response = await axios({
                method: 'POST',
                url: API_ENDPOINT
            })
            console.log('Response: ', response.data)
            console.log('Uploading: ', this.image)

            let binary = atob(this.image.split(',')[1])
            let array = []
            for (var i = 0; i < binary.length; i++) {
                array.push(binary.charCodeAt(i))
            }
            let blobData = new Blob([new Uint8Array(array)], {type: 'image/jpeg'})
            console.log('Uploading to: ', response.data.uploadURL)
            const result = await fetch(response.data.uploadURL, {
                method: 'PUT',
                headers: { 
                    'Content-Type': 'image/jpeg', 
                    'x-amz-acl': 'public-read' },
                body: blobData
            })
            console.log('Result: ', result)
            // Final URL for the user doesn't need the query string params
            this.uploadURL = response.data.uploadURL.split('?')[0]
        }

不幸的是,我在使用签名URL时遇到了一个禁止的403错误。以下是我从Chrome浏览器中获得的控制台错误的结果:

上传至:https://s3.us-west-2.amazonaws.com/pics.amazon-clone.io/b1bdb5e3-7f64-49f7-b779-11b3f67317ee.jpg?Content-类型=图像/jpeg

vue?937b:60个选项https://s3.us-west-2.amazonaws.com/pics.amazon-clone.io/b1bdb5e3-7f64-49f7-b779-11b3f67317ee.jpg?Content-类型=图像/jpeg

在'https://s3.us-west-2.amazonaws.com/pics.amazon-clone.io/b1bdb5e3-7f64-49f7-b779-11b3f67317ee.jpg?Content-类型=图像/jpeg

共有3个答案

东门修能
2023-03-14

我也有403个错误。

在我的例子中,我只是设置了SignatureVersion,并解决了它。

之前

const s3 = new aws.S3();

之后

const s3 = new aws.S3({ signatureVersion: 'v4' });
丁阳炎
2023-03-14

以下是我将如何排除故障。我会首先确认生成的URL正在使用一些工具,如curl或postman,然后我会检查发送到s3的请求,并寻找请求中存在的任何其他标题。

我会尝试通过curl/postman上传,看看URL是否正常工作。

curl -X PUT -T ~/Downloads/car.jpg https://s3.us-west-2.amazonaws.com/pics.amazon-clone.io/b1bdb5e3-7f64-49f7-b779-11b3f67317ee.jpg?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASGDJJ5ZLUVPMUYMQ%2F20200129%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20200129T165522Z&X-Amz-Expires=900&X-Amz-Signature=b230c9a40065585307e150655466bbab3d0d99aa43f8620377ab977eb1c7234c&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read

如果可以确认步骤1正在工作,则可以使用浏览器的“网络”选项卡检查随请求发送的实际标头。查看代码是否在您不知情的情况下发送了任何其他标题。

希望这有帮助。

屠嘉
2023-03-14

当你有选择的时候-

要解决此问题,您必须更新bucket的权限配置。

要做到这一点,去你的桶-

然后将以下代码放入其中:

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

不要忘记替换

If you want to allow all domains just replace this line

<AllowedOrigin><YOUR_DOMAIN></AllowedOrigin> 

with this

<AllowedOrigin>*</AllowedOrigin>

 类似资料:
  • 我正在使用预签名aws lambda中的WebSocket url,使用Amazon Kinesis Video Streams WebRTC SDK for JavaScript 在客户机中,当试图使用从服务器返回预签名url的requestSigner调用时,我会得到以下错误: 原因是什么? 这可能是CORS的问题吗? 也许url缺少令牌或标头?

  • 使用curl或postman,我得到403禁止: Lambda函数具有以下权限: S3桶具有以下CORS规则:

  • 我知道使用以下方法限制对象的上载大小:http://doc.s3.amazonaws.com/proposals/post.html#limiting_uploaded_content 但是我想知道如何在服务器端以IAM用户的身份使用S3 SDK生成预签名url的同时完成。

  • 我正在使用预先签名的URL将视频上载到AWS S3,上载成功,但当我尝试从S3下载视频并在媒体播放器(VLC或quickTime)中播放时,它不播放! 生成的预签名URL在中运行良好,但在和中也会出现与上述相同的问题。

  • 我试图使用angular客户端将文件上传到Amazon S3。我已经使用NodeJs应用服务器生成了一个预先签名的URL。在将文件上传到预先签名的URL时,我收到一个错误,如下所示: "对预检请求的响应没有通过权限改造检查:请求的资源上没有'Access-Control-Allow-Origin'标头。因此不允许访问Origin'http://localhost:4200'。" 我已将以下 COR

  • 我们得到一个 缺少Key-Pair-Id查询参数或cookie值 使用我们的PHP签名url时出现CloudFront错误。 AWS PHP SDK创建的签名url是: https://d1abv849wt1uqs.cloudfront.net/7f495b8f-c7a9-4359-8e35-a20cccb62f83/hls/SampleVideo2.m3u8?Expires=1585578292