问题
I have been trying to save user uploaded files to my s3 bucket via my django application. I'm using the django-s3-storage middleware, but I keep getting:
S3ResponseError: 403 Forbidden (Access Denied)
I'm using these settings:
MEDIAFILES_LOCATION = 'media'
AWS_S3_CUSTOM_DOMAIN = 'my-bucket.s3-website-eu-west-1.amazonaws.com'
AWS_S3_HOST = 's3-website-eu-west-1.amazonaws.com'
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'django_s3_storage.storage.StaticS3Storage'
#S3 settings from https://github.com/etianen/django-s3-storage
AWS_ACCESS_KEY_ID = "xxx"
AWS_SECRET_ACCESS_KEY = "yyy"
AWS_S3_BUCKET_NAME = "my-bucket"
AWS_S3_CALLING_FORMAT = "boto.s3.connection.OrdinaryCallingFormat"
# Make user uploaded files public
AWS_S3_BUCKET_AUTH = False
AWS_S3_MAX_AGE_SECONDS = 60*60*24*365 # 1 year
AWS_S3_GZIP = True
And I know the credentials are valid:
from boto.s3.connection import S3Connection
from django.conf import settings
conn = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
b = conn.get_bucket('my-bucket')
key = b.get_key('test.txt')
print(key.get_contents_as_string())
>>>this is a test
from boto.s3.key import Key
k = Key(b)
k.key = 'test2.txt'
k.set_contents_from_string('another test')
>>>12
I've set a completely open CORS policy too (while trying to get this working from my dev machine):
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
So what's stopping me authenticating via the middleware? (Or what else could be causing the 403?)
Edit:
bucket policy allowing access to IAM user production
for bucket my-bucket
. I've removed the user ARN digits and replaced with x
.
{
"Version": "2016-12-30",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxxx:user/production"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
The error is not a signature error as per this bug. I'm on django 1.10, boto 2.45, django-s3-storage 0.9.11.
S3ResponseError at /the-url/
S3ResponseError: 403 Forbidden
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message>
Edit 2:
OK, this weird thing happened (I don't recall having changed anything in the settings to cause this): I upload a file, and no error is returned. The file is saved as per the model definition image0 = models.ImageField(upload_to="product_images")
. The file is then available at https://s3.amazonaws.com:443/productimages/myimage.jpg
(huh? why?). It is not available at http://my-bucket.s3-website-eu-west-1.amazonaws.com/media/productimages/myimage.jpg
, nor is it visible in my bucket's media/productimages/myimage.jpg
.
So it seems that something funny is going on with either s3 or the middleware. Any ideas?
回答1:
Using bucket described here. There are two access methods - path, and virtual hosted. More on that here. Is your bucket name is DNS compliant?
来源:https://stackoverflow.com/questions/41399502/getting-http403-when-saving-files-through-django-s3-middleware-but-can-save-usi