Как я могу определить фактический URL-адрес, который клиент использовал для доступа к веб-службе Django?

Я реализовал схему аутентификации, которая имитирует то, что Amazon делает с S3 в моем веб-сервисе Django. Каждый запрос подписывается с использованием секрета. Подписываемая строка включает, среди прочего, URL-адрес ресурса, к которому осуществляется доступ.

Например, если клиент отправляет запрос GET для http://myservices.org/users, клиент должен создать string_to_sign, который содержит http://myservices.org/users. Когда сервер обрабатывает запрос, он также создает string_to_sign и может включать тот же URL-адрес на основе информации, которую он получает из объекта запроса-оболочки WSGI.

Моя проблема заключается в том, что когда клиент решает указать номер порта (например, http://myservices.org:80/users), тогда код сервера создает неверный string_to_sign, потому что я не знаю, как получить фактический URL-адрес, который использовался клиентом. Оболочка WSGI не сообщает мне, что URL-адрес включает номер порта.

Есть ли способ для приложения Django узнать фактический URL-адрес, который был частью HTTP-запроса? Нужно ли мне настраивать какой-то обработчик запросов, который находится перед оболочкой WSGI, чтобы получить доступ к необработанному HTTP-запросу и самостоятельно извлечь URL-адрес?


person Bennett Smith    schedule 06.07.2012    source источник


Ответы (2)


Вы просите невозможного. Все, что у вас есть, это первая строка запроса, которая не включает сетевое расположение (имя хоста и номер порта). Обычно вы получаете заголовок узла (HTTP 1.0 или лучше), который может включать или не включать номер порта.

Возможно, вы захотите взглянуть на django-fost-authn, который реализует схему, очень похожую на схему Amazon.

Даже если вы не используете это и предпочитаете свое собственное, вы должны увидеть, как выполняется нормализация запроса там до расчета подписи. Наиболее уместным наблюдением является то, что он использует факторы только внутри самого HTTP-запроса. Это позволяет добавлять пользовательские заголовки, которые будут включены в набор подписанных заголовков, и вы можете настаивать на том, чтобы для того, что вы хотите, заголовок узла был подписан.

Обратите особое внимание на то, как создается документ в fost-authn/signature.py.

person KayEss    schedule 06.07.2012

Хотя это может не всегда работать с разными браузерами и версиями HTTP, вы можете использовать request.META['HTTP_HOST']. Для моего локального сервера разработки прямо сейчас это возвращает localhost: 8000, который я мог бы затем разделить двоеточием посередине, чтобы получить обе части по отдельности.

Кроме того, вы можете найти применение методу get_host() в классе HttpRequest. Из документации Django:

Возвращает исходный хост запроса, используя информацию из заголовков HTTP_X_FORWARDED_HOST (если включен USE_X_FORWARDED_HOST) и заголовков HTTP_HOST в указанном порядке. Если они не предоставляют значение, метод использует комбинацию SERVER_NAME и SERVER_PORT, как описано в PEP 3333.

Пример: 127.0.0.1:8000

person zacharytamas    schedule 06.07.2012