Несогласованная подпись не соответствует Amazon S3 с django-pipeline, s3boto и хранилищами

У меня есть 2 файла, скомпилированных django-pipeline вместе с s3boto: master.css и master.js. В моих корзинах они установлены как «общедоступные». Однако, когда я обращаюсь к ним, иногда обслуживается master.css, иногда возникает ошибка SignatureDoesNotMatch. То же самое с master.js. Этого не происходит в Chrome. Что я мог упустить?

EDIT: теперь это происходит и в Chrome.


person yretuta    schedule 05.08.2012    source источник


Ответы (5)


Со мной тоже случилось... Потребовалось несколько часов, чтобы найти, но в конце концов я понял это. Оказывается, если правильная подпись:

ссCNsAOxLf5vA80ldAI3M0CU2%2Bw=

Тогда AWS НЕ примет:

ссCNsAOxLf5vA80ldAI3M0CU2+w=

Где единственная разница заключается в переводе %2B в «+».

S3BotoStorage на самом деле дает это правильно, но кодирование происходит в CachedFilesMixin в последней строке метода URL (return unquote(final_url)). Чтобы исправить это, я получил новый 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))

Где я использовал код, который я нашел здесь.

Надеюсь это поможет...

person idanzalz    schedule 04.09.2012
comment
Я попробую применить его, но можете ли вы проверить эту модификацию по этой проблеме: stackoverflow.com/questions/12006894/ - person yretuta; 05.09.2012
comment
это сработало. однако, как указано выше, может не быть проблем с boto или нет, и я, конечно, не хотел бы применять этот патч каждый раз, когда хочу использовать boto для проекта. Не могли бы вы посмотреть на проблему и увидеть, что вы придумали? Спасибо! - person yretuta; 05.09.2012
comment
проблема с boto заключается в том, что он не должен генерировать подписи с пробелами и кодировать их как знаки +. - person yretuta; 05.09.2012
comment
Я не думаю, что проблема в бото, кажется, он дает правильную подпись. проблема заключается в CachedFilesMixin django, который преобразует% 2B в «+». У меня есть запрос на включение в Django, чтобы удалить вызов без кавычек в конце CachedFilesMixin.url - person idanzalz; 05.09.2012
comment
@idanzalz хотите дать ссылку на пулреквест? Я бы очень хотел знать, войдет ли это. - person Stuart Axon; 16.09.2013
comment
к сожалению, запрос на вытягивание не был принят. см. здесь: code.djangoproject.com/ticket/18929 - person idanzalz; 24.09.2013

У меня была аналогичная проблема, вызывающая ошибки SignatureDoesNotMatch при загрузке файлов с использованием подписанного URL-адреса S3, а библиотека python запрашивает HTTP.

Моя проблема оказалась плохим типом контента. Документация AWS по Аутентификация запросов REST помогла мне разобраться. , и есть примеры на Python.

person cbare    schedule 19.02.2013
comment
Я отправлял файл InMemoryUploadedFile и забыл установить тип содержимого. Все работает нормально, как только я правильно установил тип контента! Спасибо за совет. - person dulaccc; 14.10.2014

Я некоторое время боролся с этим, и мне не нравилась идея возиться с CachedFilesMixin (мне это казалось излишним).

Пока для платформы django не будет выпущено надлежащее исправление, я обнаружил, что двойное цитирование подписи является хорошим вариантом. Я знаю, что это не очень красиво, но это работает и это просто.

Так что вам просто нужно сделать что-то вроде этого:

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

Надеюсь, поможет!

person Luis Santos del Val    schedule 20.12.2013

Эта статья о 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
    })
person Philip Nuzhnyy    schedule 02.09.2013

Простой обходной путь для меня заключался в создании нового ключа доступа только с буквенно-цифровыми символами (т. е. без специальных символов, таких как «/», «+» и т. д., которые AWS иногда добавляет к ключам).

person Ludwig Konrad Bull    schedule 05.08.2019