使用Heroku的指南使用Python上传到AWS S3,获得403

时间:2015-02-25 05:18:04

标签: python heroku amazon-s3

我正在浏览Heroku关于使用Javascript https://devcenter.heroku.com/articles/s3-upload-python将图像上传到亚马逊的教程。

根据教程,我似乎已经完成了所有工作,但我仍然收到了403 Access Denied错误。

我的存储桶名为media.better.herokuapp.com,它对应于S3_BUCKET环境变量。从Amazon Web界面仔细复制AWS_ACCESS_KEYAWS_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" -

那还缺少什么?

我正在看的选项是:

  • 上传的文件命名有问题 - 如果你看 在request.GET dict中,JS库命名所有输入文件 default_name
  • AWS的帐户凭据以某种方式启用OPTIONS个请求 但禁用PUT请求,必须解决这些问题 具体而言,虽然AWS手册说它们是系统范围的
  • 必须以某种方式单独将localhost来源添加到CORS配置

还是有其他的东西?

0 个答案:

没有答案