Amazon S3上传响应HTTP 403:访问被拒绝 - python

这将是一篇很长的文章,但是由于我不知道哪里出了问题,所以我认为最好是过于冗长而不是忽略必要的信息。

我正在尝试按照以下指南将图像上传到我的Amazon S3存储桶:https://devcenter.heroku.com/articles/s3-upload-python。

我将代码设置如下:

index.html

<img id="preview" src="https://via.placeholder.com/320?text=Image+Upload">
<input id="file_input" class="form-control" type="file" name="image" accept="image/*">
<form method="POST" action="/gallery/upload" enctype="multipart/form-data">
    <input type="hidden" name="csrfmiddlewaretoken" value="lVE...ASG">
    <input type="hidden" id="image-url" name="image-url">
    <input class="form-control" type="text" name="title" placeholder="Title">
    <input class="form-control" type="text" name="price" placeholder="Price">
    <div class="form-control">
        <input type="checkbox" name="archive" value="True">
        <label for="archive">Archive</label>
    </div>
    <input class="form-control btn-primary" type="submit">
</form>

s3.js

function uploadFile(file, s3Data, url) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", s3Data.url);

    var postData = new FormData();
    for (key in s3Data.fields) {
        postData.append(key, s3Data.fields[key]);
    }
    postData.append('file', file);
    for (var [key, value] of postData.entries()) {
        console.log(key + ': ' + value);
    }

    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200 || xhr.status === 204) {
                document.getElementById("preview").src = url;
                document.getElementById("image-url").value = url;
            }
            else {
                alert("Could not upload file.");
            }
        }
    };
    xhr.send(postData);
}

function getSignedRequest(file) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/gallery/sign_s3?file_name="
                    + file.name + "&file_type=" + file.type);
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                var response = JSON.parse(xhr.responseText);
                uploadFile(file, response.data, response.url);
            }
            else {
                alert("Could not get signed URL.");
            }
        }
    };
    xhr.send();
}

$(document).ready(function () {
    (function () {
        document.getElementById("file_input").onchange = function () {
            var files = document.getElementById("file_input").files;
            var file = files[0];
            if (!file) {
                return alert("No file selected.");
            }
            getSignedRequest(file);
        };
    })();
});

views.py

S3_BUCKET = os.environ.get('S3_BUCKET')
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
s3 = boto3.client(
    's3',
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)

def sign_s3(request):
    file_name = request.GET.get('file_name')
    file_type = request.GET.get('file_type')

    presigned_post = s3.generate_presigned_post(
        Bucket=S3_BUCKET,
        Key=file_name,
        Fields={"acl": "public-read", "Content-Type": file_type},
        Conditions=[
            {"acl": "public-read"},
            {"Content-Type": file_type}
        ],
        ExpiresIn=3600
    )

    return JsonResponse({
        'data': presigned_post,
        'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
    })

当我使用文件上传器选择图片时,我收到一条警告,提示“无法上传文件”,以及来自Chrome开发者控制台的以下输出:

acl: public-read
Content-Type: image/jpeg
key: dragon.jpg
x-amz-algorithm: AWS4-HMAC-SHA256
x-amz-credential: AKI...TRA/20190224/us-east-2/s3/aws4_request
x-amz-date: 20190224T044659Z
policy: eyJ...XX0=
x-amz-signature: 7ea...18a
file: [object File]

看起来预签名已经通过了,但是我从上传中得到了以下XML:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>5D1...AB5</RequestId>
  <HostId>cYX...WKw=</HostId>
</Error>

我的CORS政策非常宽大(我计划稍后再进行更改,但现在,我想防止访问受到限制):

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

我尝试编辑存储桶策略,但仍然收到“访问被拒绝”错误。该指南没什么用:https://aws.amazon.com/premiumsupport/knowledge-center/s3-access-denied-bucket-policy/

我不知道是什么原因造成的,但是我猜是某个地方存在权限问题。我不知道在哪里任何帮助表示赞赏。

编辑:用户的策略是AdministratorAccessAmazonS3FullAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

编辑2:通过取消选中“公共访问设置”中的“阻止新的公共存储桶策略”,我可以对存储桶策略进行更改。将其设置为以下值不再导致“存储桶策略”页面上出现“访问被拒绝”错误消息,但是我仍然无法通过XHR上传文件:

{
    "Id": "Policy...237",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt...935",
            "Action": "s3:*",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::coolwater-creations/*",
            "Principal": {
                "AWS": [
                    "...764"
                ]
            }
        }
    ]
}

参考方案

我怀疑您使用的帐户与您在IAM中看到的帐户不同:

在您共享的屏幕截图中,您会注意到IAM用户名在屏幕截图中与您的用户名不匹配

Amazon S3上传响应HTTP 403:访问被拒绝 - python

如果您以该IAM用户身份登录,则应该在用户名中看到相同的名称

Amazon S3上传响应HTTP 403:访问被拒绝 - python

因此,您要么以root帐户身份登录,在这种情况下,错误将出在创建存储桶的方式上(请检查https://aws.amazon.com/premiumsupport/knowledge-center/s3-troubleshoot-403/)
或者您正在使用AWS合作伙伴的SSO登录,在这种情况下,您在其中的权限会有所不同,并且不受您在那里看到的IAM的控制。

Python uuid4,如何限制唯一字符的长度 - python

在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…

Python:无法识别Pip命令 - python

这是我拍摄的屏幕截图。当我尝试在命令提示符下使用pip时,出现以下错误消息:pip无法识别为内部或外部命令,可操作程序或批处理文件。我已经检查了这个线程:How do I install pip on Windows?我所能找到的就是我必须将"C:\PythonX\Scripts"添加到我的类路径中,其中X代表python版本。如您在我的…

Python:如何将有效的uuid从String转换为UUID? - python

我收到的数据是 { "name": "Unknown", "parent": "Uncategorized", "uuid": "06335e84-2872-4914-8c5d-3ed07d2a2f16" }, 我需要将uuid从Strin…

Python 3会流行吗? - python

我已经学习了一些Python 2和Python 3,似乎Python 2总体上比Python 3更好。这就是我的问题所在。是否有充分的理由真正切换到python 3? 参考方案 总体上,甚至在大多数细节上,Python3都比Python2更好。关于第三方库, Python 3落后于的唯一区域是。使Python变得如此出色的原因不仅在于它作为一种语言的内在特性…

python 。向字典中的键添加多个项目 - python

我正在尝试根据一组唯一值构建一个字典,以用作键和提供项目的元组压缩列表。set = ("a","b","c") lst 1 =("a","a","b","b","c","d",&#…