简体   繁体   English

AWS S3 存储桶 Django 3.0 用户配置文件图像上传访问错误

[英]AWS S3 Bucket Django 3.0 User Profile Image Upload Access ERROR

INTRO介绍

  • I am following this guide as recommended, here is the guide's GitHub repo .我按照建议遵循指南,这是该指南的 GitHub 存储库
  • I have created an AmazonS3FullAccess to it as well我也为它创建了一个 AmazonS3FullAccess
  • I am using the guide's 3rd example " Mixing public assets and private assets " with static, media public, media, private version.我正在使用指南的第三个示例“混合公共资产和私人资产”与 static、媒体公共、媒体、私人版本。
  • If the user log in (local development environment) he Upload Files from the website but he can NOT access them from the website only from the AWS S3 management website.如果用户登录(本地开发环境),他会从网站上传文件,但他不能仅从 AWS S3 管理网站从网站访问它们。
  • Currently I am blocking all public access as it is in the guide (AWS S3 management panel settings)目前我正在阻止所有公共访问,因为它在指南中(AWS S3 管理面板设置)
  • I have added these lines to my CORS configuration editor from this other guide我已将这些行添加到此其他指南中的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>
  • Switched on a central EU server that is more local to me.打开对我来说更本地的中央欧盟服务器。 NOT worked I got the same error.不工作我得到了同样的错误。

storage_backends.py storage_backends.py

from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage

class StaticStorage(S3Boto3Storage):
    location = settings.AWS_STATIC_LOCATION

class PublicMediaStorage(S3Boto3Storage):
    location = settings.AWS_PUBLIC_MEDIA_LOCATION
    file_overwrite = False

class PrivateMediaStorage(S3Boto3Storage):
    location = settings.AWS_PRIVATE_MEDIA_LOCATION
    default_acl = 'private'
    file_overwrite = False
    custom_domain = False

settings.py设置.py

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'MYPROJECTS_MAIN_APP/static'),]

AWS_ACCESS_KEY_ID = 'DSHUGASGHLASF678FSHAFH'
AWS_SECRET_ACCESS_KEY = 'uhsdgahsfgskajgjkafgjkdfjkgkjdfgfg'
AWS_STORAGE_BUCKET_NAME = 'MYSTORAGE289377923'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}

AWS_STATIC_LOCATION = 'static'
STATICFILES_STORAGE = 'mysite.storage_backends.StaticStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_STATIC_LOCATION)

AWS_PUBLIC_MEDIA_LOCATION = 'media/public'
DEFAULT_FILE_STORAGE = 'mysite.storage_backends.PublicMediaStorage'

AWS_PRIVATE_MEDIA_LOCATION = 'media/private'
PRIVATE_FILE_STORAGE = 'mysite.storage_backends.PrivateMediaStorage'

AWS_S3_HOST = "s3.eu-central-1.amazonaws.com"
S3_USE_SIGV4 = True
AWS_S3_REGION_NAME = "eu-central-1"

models.py模型.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User

from mysite.storage_backends import PrivateMediaStorage


class Document(models.Model):
    uploaded_at = models.DateTimeField(auto_now_add=True)
    upload = models.FileField()


class PrivateDocument(models.Model):
    uploaded_at = models.DateTimeField(auto_now_add=True)
    upload = models.FileField(storage=PrivateMediaStorage())
    user = models.ForeignKey(User, related_name='documents')

views.py视图.py

from django.contrib.auth.decorators import login_required
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator

from .models import Document, PrivateDocument


class DocumentCreateView(CreateView):
    model = Document
    fields = ['upload', ]
    success_url = reverse_lazy('home')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        documents = Document.objects.all()
        context['documents'] = documents
        return context


@method_decorator(login_required, name='dispatch')
class PrivateDocumentCreateView(CreateView):
    model = PrivateDocument
    fields = ['upload', ]
    success_url = reverse_lazy('profile')

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save()
        return super().form_valid(form)

ERROR错误

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>56fg67dfg56df7g67df</RequestId>
<HostId>
hsiugYIGYfhuieHF7weg68g678dsgds78g67dsg86sdg68ds7g68ds7yfsd8f8hd7
</HostId>
</Error>

Things That I have Tried So Far到目前为止我尝试过的事情

  • There was an in between period where it have created the AWS link and also added the file to a local "media" folder.在此期间,它创建了 AWS 链接并将文件添加到本地“媒体”文件夹。 But since I have deleted the"Media folder" and it only creates URL links, and actually uploads them to the S3 bucket但由于我删除了“媒体文件夹”,它只创建了 URL 链接,实际上将它们上传到 S3 存储桶
  • I have found the same question on aws forum but it has not been answered我在aws论坛上发现了同样的问题,但没有得到回答
  • Access rights Django + AWS S3 Bucket: Authenticated Access to S3 Bucket (I don't understand this answer https://stackoverflow.com/a/21614550/10270590 )访问权限Django + AWS S3 Bucket:Authenticated Access to S3 Bucket (我不明白这个答案https://stackoverflow.com/a/21614550/10270590
  • "use AWS4-HMAC-SHA256" “使用 AWS4-HMAC-SHA256”
    • Specifying region of the S3 host to the correct usage https://github.com/aws/aws-sdk-js/issues/829指定 S3 主机的区域以正确使用https://github.com/aws/aws-sdk-js/issues/829
    • site to look up your region - https://docs.aws.amazon.com/general/latest/gr/rande.html查找您所在地区的站点 - https://docs.aws.amazon.com/general/latest/gr/rande.html
    • I have also received this as a recommendation "Most new regions only support AWS4-HMAC-SHA256 - if your code doesn't support this authentication scheme and only created "v2 signatures" create your bucket in one of the old regions, eg in Europe it seems to be only Ireland - check it out here: https://docs.aws.amazon.com/general/latest/gr/signature-version-2.html "我还收到了此建议“大多数新区域仅支持AWS4-HMAC-SHA256 - 如果您的代码不支持此身份验证方案并且仅创建“v2 签名” ,请在其中一个旧区域创建您的存储桶,例如在欧洲似乎只有爱尔兰- 在这里查看: https://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
    • I am in the European Union with my testing machine - and I set up a USA base S3 bucket - how can I configure the Django app OR the AWS S3 Bucket so it will allow it to be accessed from anywhere (it would be especially important that the app is deployed that from around the world people can access it).我在欧盟使用我的测试机 - 我设置了一个美国基地 S3 存储桶- 我如何配置 Django 应用程序或 AWS S3 存储桶,以便它可以从任何地方访问它(尤其重要的是该应用程序已部署,来自世界各地的人们都可以访问它)。 A guy from the same video's comment section commented the the following Steve D Great video series, just to say I am using an S3 bucket in Europe and needed to add additional settings AWS_S3_HOST = "s3.eu-west-2.amazonaws.com" and AWS_S3_REGION_NAME="eu-west-2" to make it work来自同一视频评论部分的人评论了以下Steve D Great video series, just to say I am using an S3 bucket in Europe and needed to add additional settings AWS_S3_HOST = "s3.eu-west-2.amazonaws.com" and AWS_S3_REGION_NAME="eu-west-2" to make it work
  • This was the exact code I have added to the settings based on and in addition to the original Guide's code.这是我根据原始指南的代码添加到设置中的确切代码。 When I switch images it works but when I leave profile settings and go back the image disappears and gives the original error):当我切换图像时它可以工作,但是当我离开配置文件设置和 go 回来时,图像消失并给出原始错误):
AWS_S3_HOST = "s3.eu-central-1.amazonaws.com"
S3_USE_SIGV4 = True
AWS_S3_REGION_NAME = "eu-central-1"
  • TRURNING OFF all Access restriction (Temporarily) and adding Bucket policies to AWS S3 Management consol关闭所有访问限制(临时)并将存储桶策略添加到 AWS S3 管理控制台
    • 1 CODE: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" ] } ] } --> ERORR 1 代码: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" ] } ] } --> 错误
    • 2 CODE: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::myprojectname_that_jsut_abow_this_field/" ] } ] }/* --> ERORR 2 代码: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::myprojectname_that_jsut_abow_this_field/" ] } ] }/* --> 错误
    • 3 CODE: I have changed to this { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "*", "Action":["s3:GetObject"], "Resource":"arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" } ] } and got the following error: Error Access denied 3 代码:我已更改为此{ "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "*", "Action":["s3:GetObject"], "Resource":"arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" } ] }并得到以下错误: Error Access denied
    • 4 CODE: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":"arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" } ] } ERROR: Error Missing required field Principal cannot be empty! 4 代码: { "Version":"2012-10-17", "Statement":[{ "Sid":"PublicReadGetObject", "Effect":"Allow", "Principal": "", "Action":["s3:GetObject"], "Resource":"arn:aws:s3:::myprojectname_that_jsut_abow_this_field/*" } ] }错误: Error Missing required field Principal cannot be empty!

In the AWS console, click the "Permissions" tab, then on the在 AWS 控制台中,单击“权限”选项卡,然后在

  1. allow public access to your bucket -> Save -> Confirm it允许公开访问您的存储桶 -> 保存 -> 确认
  2. "Bucket policy" button. “存储桶策略”按钮。 An editing box will appear.将出现一个编辑框。 Replace the "arn:aws:s3:::" in the editing box with the part starting with "arn:" shown above your editing box, but be careful to preserve the "/*" at the end of it.将编辑框中的“arn:aws:s3:::”替换为编辑框上方显示的以“arn:”开头的部分,但请注意保留其末尾的“/*”。 Use the following code bellow.使用下面的代码。 Paste in the following:粘贴以下内容:
 {
  "Version":"2012-10-17",
  "Statement":[{
    "Sid":"PublicReadGetObject",
        "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::your-buckt-arn/*"
      ]
    }
  ]
}

Not sure if you are still trying the issue.不确定您是否仍在尝试该问题。

You can try adding a parameter: AWS_DEFAULT_ACL = 'public-read' in your setting.py您可以尝试在 setting.py 中添加参数:AWS_DEFAULT_ACL = 'public-read'

Delete all the previously uploaded files in your bucket.删除存储桶中所有之前上传的文件。

Re-upload media and static files.重新上传媒体和 static 文件。

See if it works.看看它是否有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM