无论我做什么,都无法使用预签名 URL 将文件上传到 S3。AWS 命令​​行有效。CURL 和其他 = 403

Jas*_*enX 6 python amazon-s3 amazon-web-services pre-signed-url

我的 AWS 凭证~/.aws/credentials正确且有效。证明?

$ aws s3api put-object --bucket <my bucket name> --key videos/uploads/yoda.jpeg --body /Users/r<my_name>/Desktop/Archive/yoda.jpeg
Run Code Online (Sandbox Code Playgroud)

取回:

{
    "ETag": "\"66bee0b7caf3d127900e0a70f2da4b5f\""
}
Run Code Online (Sandbox Code Playgroud)

上传是通过命令行进行的。当我在 AWS 管理控制台中看到我的 S3 存储桶时,我就可以看到我的文件。

现在-我从 S3 中删除了成功上传的文件,并尝试再次上传它,这次是通过预先签名的 URL

$ aws s3 presign s3://<my-bucket>/videos/uploads/yoda.jpeg
Run Code Online (Sandbox Code Playgroud)

为此我得到:

https://<my-bucket>.s3.amazonaws.com/videos/uploads/yoda.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=3600&X-Amz-Credential=<MY-AWS-KEY-ID>%2F20210207%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Date=20210207T222859Z&X-Amz-Signature=3a3624b9e264c119ebdf93c989efb73337f7ab8793e89554c7b000e1fc93c85c
Run Code Online (Sandbox Code Playgroud)

从这一刻起,使用此 URL 或任何其他工具进行的任何尝试PUT都 无法上传文件,最终都会以(是的,它不会过期,它会立即失败)告终,并且这是 AWS 提供的借口。CURLPOSTMAN403The request signature we calculated does not match the signature you provided

/.aws/credentialsS3 存储桶有一项策略,允许其凭据位于该存储桶中的用户Put*

到底是怎么回事?为什么预签名 URL 不起作用?

卷曲尝试

$ curl --location --request PUT 'https://<my-bucket-name>.s3.amazonaws.com/videos/uploads/yoda.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=3600&X-Amz-Credential=<MY-AWS-KEY-ID>%2F20210207%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Date=20210207T224403Z&X-Amz-Signature=8a8625591e6c4e0871f97bf5e15c2f93b3e373cfc1c2daddb2cf34edb10a5670%0A' \
--header 'Content-Type: image/jpeg' \
--data-binary '@/Users/<MY-NAME>/Desktop/Archive/yoda.jpeg'
Run Code Online (Sandbox Code Playgroud)

我得到:

$ aws s3 presign s3://<my-bucket>/videos/uploads/yoda.jpeg
Run Code Online (Sandbox Code Playgroud)

尝试从 PYTHON 生成 PRESIGN URL。还是不行。URL 有错误 - AWS 拒绝同样的 403

https://<my-bucket>.s3.amazonaws.com/videos/uploads/yoda.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=3600&X-Amz-Credential=<MY-AWS-KEY-ID>%2F20210207%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Date=20210207T222859Z&X-Amz-Signature=3a3624b9e264c119ebdf93c989efb73337f7ab8793e89554c7b000e1fc93c85c
Run Code Online (Sandbox Code Playgroud)

由此生成的 URL:

https://<my-bucket>.s3.amazonaws.com//videos/uploads/yoda.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<my-AWS-KEY-ID>%2F20210207%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20210207T231306Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=968a3e2cab9b7e907df69e24aae24d79ea40f52a52d407591d7cbd69c86fe67b
Run Code Online (Sandbox Code Playgroud)

冰壶得到相同的403。没有改变。

Jas*_*enX 3

解决方案:原来我使用的 Boto3 不是最新的,而且我使用了错误的方法。修复这些问题后,对我有用的代码是:

# THE CREDENTIALS ARE PART OF MY TESTING CODE. NO WORRIES THEY'RE IN AN ENV VARIABLE NOW

def get_upload_pre_signed_url(bucket_name, key, expiration=3600):
    s3 = boto3.client('s3',
                      aws_access_key_id="<my access_key_id",
                      aws_secret_access_key="<my_secreet_access_key>",
                      config=Config(region_name='us-east-2', s3.{"use_accelerate_endpoint": True}))

    try:
        url = s3.generate_presigned_url('put_object', Params={'Bucket': bucket_name, 'Key': key},
                                        ExpiresIn=expiration,
                                        HttpMethod='PUT')
    except ClientError as e:
        return None

    return url
Run Code Online (Sandbox Code Playgroud)