我正在浏览Heroku关于使用Javascript https://devcenter.heroku.com/articles/s3-upload-python将图像上传到亚马逊的教程。
根据教程,我似乎已经完成了所有工作,但我仍然收到了403 Access Denied错误。
我的存储桶名为media.better.herokuapp.com,它对应于S3_BUCKET
环境变量。从Amazon Web界面仔细复制AWS_ACCESS_KEY
和AWS_SECRET_KEY
个变量。这些不是用户凭据,而是帐户凭据,
“提供对您的AWS资源的无限制访问权。”
生成请求网址的代码:
@login_required
def sign_s3(request):
AWS_ACCESS_KEY = os.environ.get('AWS_ACCESS_KEY')
AWS_SECRET_KEY = os.environ.get('AWS_SECRET_KEY')
S3_BUCKET = os.environ.get('S3_BUCKET')
object_name = request.GET.get('s3_object_name')
mime_type = request.GET.get('s3_object_type')
expires = long(time.time()+10)
amz_headers = "x-amz-acl:public-read"
put_request = "PUT\n\n%s\n%d\n%s\n/%s/%s" % (mime_type, expires, amz_headers, S3_BUCKET, object_name)
signature = base64.encodestring(hmac.new(AWS_SECRET_KEY, put_request, sha1).digest())
signature = urllib.quote(urllib.quote_plus(signature.strip()))
url = 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, object_name)
return HttpResponse(
json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url
})
)
实际发送请求的代码,基于s3upload.js library,根据Heroku教程再次全部:
<script>
function s3_upload(){
var status_elem = document.getElementById("status");
var url_elem = document.getElementById("avatar_url");
var preview_elem = document.getElementById("preview");
var s3upload = new S3Upload({
file_dom_selector: 'file',
s3_sign_put_url: '/sign_s3/',
onProgress: function(percent, message) {
status_elem.innerHTML = 'Upload progress: ' + percent + '% ' + message;
},
onFinishS3Put: function(url) {
status_elem.innerHTML = 'Upload completed. Uploaded to: '+ url;
url_elem.value = url;
preview_elem.innerHTML = '<img src="'+url+'" style="width:300px;" />';
},
onError: function(status) {
console.log(status);
status_elem.innerHTML = 'Upload error: ' + status;
}
});
}
</script>
我的存储桶的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>
我的存储桶的日志显示有两个请求,一个OPTIONS
和一个PUT
。第一个通过(由代码200判断),第二个没有通过。
149cbdd537e09d49c6f979053efd3c99ab2a75b0d80bb72dabe40782d9f6e68e media.better.herokuapp.com [25/Feb/2015:03:58:32 +0000] 103.247.121.189 - 5AFE4968D1986AFD REST.OPTIONS.PREFLIGHT default_name "OPTIONS /default_name?AWSAccessKeyId=AKIAJTAAJTDNVNPEVKJA&Expires=1424836708&Signature=9G6eOA1%252BUDhpGcem4JOODG2up1c%253D HTTP/1.1" 200 - - - 12 - "http://localhost:8000/game/c54b02c3/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36" -
149cbdd537e09d49c6f979053efd3c99ab2a75b0d80bb72dabe40782d9f6e68e media.better.herokuapp.com [25/Feb/2015:03:58:33 +0000] 103.247.121.189 - 73F995CAE6564A1A REST.PUT.OBJECT default_name "PUT /default_name?AWSAccessKeyId=AKIAJTAAJTDNVNPEVKJA&Expires=1424836708&Signature=9G6eOA1%252BUDhpGcem4JOODG2up1c%253D HTTP/1.1" 403 AccessDenied 321 - 5 - "http://localhost:8000/game/c54b02c3/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36" -
那还缺少什么?
我正在看的选项是:
default_name
OPTIONS
个请求
但禁用PUT
请求,必须解决这些问题
具体而言,虽然AWS手册说它们是系统范围的localhost
来源添加到CORS配置还是有其他的东西?