3

s3boto とともに django-pipeline によってコンパイルされた 2 つのファイルがあります: master.css と master.js。それらは私のバケットで「公開」に設定されています。ただし、それらにアクセスすると、master.css が提供されることもあれば、SignatureDoesNotMatch でエラーになることもあります。master.js も同様です。これは Chrome では発生しません。何が欠けている可能性がありますか?

編集:Chromeでも発生するようになりました。

4

5 に答える 5

13

私にも起こりました...見つけるのに数時間かかりましたが、最終的にはわかりました。正しい署名が次の場合:

ssCNsAOxLf5vA80ldAI3M0CU2%2Bw=

その場合、AWS は以下を受け入れません。

ssCNsAOxLf5vA80ldAI3M0CU2+w=

唯一の違いは、%2B から '+' への変換です。

S3BotoStorage は実際には正しく生成しますが、エンコーディングは url メソッドの最終行の CachedFilesMixin で行われます ( return unquote(final_url))。それを修正するために、新しい CachedFilesMixin を派生させて「損傷」を元に戻しました (この unquote が最初に存在する理由がわからないため、元に戻すと他の問題が発生する可能性があることに言及する必要があります)。

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))

ここで見つけたコードを使用した場所。

お役に立てれば...

于 2012-09-04T10:59:38.350 に答える
2

S3 署名付き URL と python requests HTTP ライブラリを使用してファイルをダウンロードするときに、SignatureDoesNotMatch エラーを引き起こす同様の問題がありました。

私の問題は、悪いコンテンツタイプでした。REST リクエストの認証に関する AWS のドキュメントは、それを理解するのに役立ち、Python での例があります。

于 2013-02-19T19:44:03.567 に答える
2

私はしばらくこれに苦労していましたが、CachedFilesMixin を台無しにするという考えは好きではありませんでした (やり過ぎのように思えました)。

django プラットフォームに適切な修正が発行されるまでは、署名を 2 回引用するのが適切なオプションであることがわかりました。きれいではないことはわかっていますが、機能し、シンプルです。

したがって、次のようにするだけです。

signature = urllib.quote_plus(signature.strip())
signature = urllib.quote_plus(signature.strip())

それが役に立てば幸い!

于 2013-12-20T21:50:10.693 に答える
0

私にとっての簡単な回避策は、英数字のみを使用して新しいアクセスキーを生成することでした (つまり、AWS がキーに追加することがある「/」、「+」などの特殊文字は使用しません)。

于 2019-08-05T19:15:41.393 に答える
0

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
    })
于 2013-09-02T22:28:37.190 に答える