我有 2 个由 django-pipeline 和 s3boto 编译的文件:master.css 和 master.js。它们在我的存储桶中设置为“公共”。但是,当我访问它们时,有时会提供 master.css,有时会出现 SignatureDoesNotMatch 错误。与 master.js 相同。这不会在 Chrome 上发生。我会错过什么?
编辑:它现在也发生在 Chrome 上。
我有 2 个由 django-pipeline 和 s3boto 编译的文件:master.css 和 master.js。它们在我的存储桶中设置为“公共”。但是,当我访问它们时,有时会提供 master.css,有时会出现 SignatureDoesNotMatch 错误。与 master.js 相同。这不会在 Chrome 上发生。我会错过什么?
编辑:它现在也发生在 Chrome 上。
也发生在我身上......花了几个小时才找到,但我最终想通了。事实证明,如果正确的签名是:
ssCNsAOxLf5vA80ldAI3M0CU2%2Bw=
那么 AWS 将不接受:
ssCNsAOxLf5vA80ldAI3M0CU2+w=
唯一的区别是将 %2B 转换为“+”。
S3BotoStorage 实际上正确地产生了它,但编码发生在 url 方法 ( return unquote(final_url)
) 的最后一行的 CachedFilesMixin 上。为了修复它,我派生了一个新的 CachedFilesMixin 来撤消“损坏”(我应该提到我不知道为什么这个取消引用首先存在,所以撤消它可能会导致其他问题)
class MyCachedFilesMixin(CachedFilesMixin):
def url(self, *a, **kw):
s = super(MyCachedFilesMixin, self).url(*a, **kw)
if isinstance(s, unicode):
s = s.encode('utf-8', 'ignore')
scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
path = urllib.quote(path, '/%')
qs = urllib.quote_plus(qs, ':&=')
return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
我在哪里使用我在这里找到的代码。
希望这可以帮助...
在使用 S3 签名 URL 和 python 请求 HTTP 库下载文件时,我遇到了导致 SignatureDoesNotMatch 错误的类似问题。
我的问题最终变成了一个糟糕的内容类型。AWS 上关于Authenticating REST Requests的文档帮助我解决了这个问题,并提供了 Python 示例。
我为此苦苦挣扎了一段时间,我不喜欢弄乱 CachedFilesMixin 的想法(对我来说似乎有点矫枉过正)。
在 django 平台发布适当的修复之前,我发现引用签名两次是一个不错的选择。我知道它不漂亮,但它很有效而且很简单。
所以你只需要做这样的事情:
signature = urllib.quote_plus(signature.strip())
signature = urllib.quote_plus(signature.strip())
希望能帮助到你!
这篇关于 Flask 的文章是获取正确签名的好资源:https ://devcenter.heroku.com/articles/s3-upload-python
@app.route('/sign_s3/')
def sign_s3():
AWS_ACCESS_KEY = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
S3_BUCKET = os.environ.get('S3_BUCKET')
object_name = request.args.get('s3_object_name')
mime_type = request.args.get('s3_object_type')
expires = int(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, sha).digest())
signature = urllib.quote_plus(signature.strip())
url = 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, object_name)
return json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url
})
对我来说简单的解决方法是生成一个只有字母数字字符的新访问密钥(即没有 AWS 有时会添加到密钥中的特殊字符,例如“/”、“+”等)。