I've attempted this:
connection = S3Connection(
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
url = connection.generate_url(
60,
'GET',
settings.AWS_STORAGE_BUCKET_NAME,
self.get_object().image,
headers={'Content-Type': 'application/octet-stream'})
but when I try to visit the signed URL I get this message:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
If I remove the headers
attribute on the other hand, I can access the image just fine. What am I doing wrong?
Pre-signed URLs are used to provide short-term access to a private object in your S3 bucket. They work by appending an AWS Access Key, expiration time, and Sigv4 signature as query parameters to the S3 object. There are two common use cases when you may want to use them: Simple, occasional sharing of private files.
To create a valid pre-signed URL for your object, you must provide your security credentials, specify a bucket name, an object key, specify the HTTP method (for instance the method is "GET" to download the object) and expiration date and time. Anyone who receives the pre-signed URL can then access the object.
There is an access check on the S3 side but that only checks whether the signer entity is allowed to get the file. You can remove that permission but that invalidates all signed URLs. Signed URLs provide secure a way to distribute private content without streaming them through the backend.
The issue is that you can't set arbitrary headers using generate_url, and while the response_headers
option exists AWS also has limited options as to what you can set. This will do what's expected in this case.
url = connection.generate_url(
60,
'GET',
settings.AWS_STORAGE_BUCKET_NAME,
self.get_object().image,
response_headers={
'response-content-type': 'application/octet-stream'
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With