У нас есть веб-сайт, работающий на Apache, доступ к которому имеет ряд статических страниц, защищенных с помощью базовой аутентификации HTTP.
Я написал новую часть сайта с помощью Django, используя встроенную в Django поддержку управления пользователями.
У меня проблема в том, что пользователям нужно один раз войти в систему с помощью базовой проверки подлинности HTTP, а затем снова с помощью формы входа в Django. Это одновременно неуклюже и очень сбивает с толку пользователей.
Мне было интересно, нашел ли кто-нибудь способ заставить Django регистрировать пользователя с использованием информации аутентификации HTTP Basic.
Я не собираюсь передавать пароль Django, но если пользователь dave был аутентифицирован Apache, он также должен автоматически войти в Django как dave.
(Один из вариантов - сделать так, чтобы Apache и Django совместно использовали хранилище пользователей, чтобы обеспечить общие имена пользователей и пароли, но это все равно будет включать два приглашения входа в систему, чего я пытаюсь избежать.)





Есть httpauth.py. Я все еще новичок в Django, поэтому понятия не имею, как он точно подходит, но он должен делать то, что вы ищете.
Обновлено: вот более длинная ветка ошибок на эту тему.
Поскольку django можно запускать несколькими способами, и только modpython обеспечивает тесную интеграцию с Apache, я не верю, что у django есть способ выполнить базовый вход в базовую аутентификацию Apache. Аутентификация действительно должна выполняться на уровне приложения, так как это даст вам гораздо больше контроля и будет проще. Вам действительно не нужны хлопоты по обмену пользовательскими данными между Python и Apache.
Если вы не против использовать исправленную версию Django, то в http://www.djangosnippets.org/snippets/56/ есть патч, который предоставит вам промежуточное ПО для поддержки базовой аутентификации.
Базовая аутентификация действительно довольно проста - если пользователь не вошел в систему, вы возвращаете код статуса, требующий аутентификации 401. Это побуждает браузер отобразить окно входа в систему. Затем браузер предоставит имя пользователя и пароль в виде строк в кодировке bas64. Запись в википедии http://en.wikipedia.org/wiki/Basic_access_authentication довольно хороша.
Если патч не делает то, что вы хотите, вы можете довольно быстро реализовать базовую аутентификацию.
Проверьте ссылки Оли. Вы в основном видите аутентифицированное имя пользователя, подтвержденное базовой HTTP-аутентификацией в Django, просматривая request.META ['REMOTE_USER'].
Обновлять: Протестировал предлагаемый патч для тикета # 689, который доступен в актуальном состоянии в репозитории здесь от telenieko git. Это применимо, по крайней мере, к ревизии 9084 Django.
Активируйте серверную часть аутентификации удаленного пользователя с помощью
RemoteUserAuthMiddleware после AuthenticationMiddlewareAUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.RemoteUserAuthBackend',)Если вы используете lighttpd и FastCGI, как я, активируйте mod_auth, создайте учетные данные для тестового пользователя (я назвал его testuser и установил 123 в качестве пароля) и настройте сайт Django на базовую аутентификацию.
Для проверки установки можно использовать следующий urls.py:
from django.conf.urls.defaults import *
from django.http import HttpResponse
from django.contrib.auth.models import User
urlpatterns = patterns('',
url(regex='^$',
view=lambda request: HttpResponse(repr(request), 'text/plain')),
url(regex='^user/$',
view=lambda request: HttpResponse(repr(request.user), 'text/plain')),
url(regex='^users/$',
view=lambda request: HttpResponse(
','.join(u.username for u in User.objects.all()),
'text/plain')),
)
После перезагрузки lighty и сервера Django FCGI загрузка корня сайта теперь запрашивает аутентификацию и принимает учетные данные testuser, а затем выводит дамп объекта запроса. В request.META должны присутствовать эти новые свойства:
'AUTH_TYPE': 'Basic'
'HTTP_AUTHORIZATION': 'Basic dGVzdHVzZXI6MTIz'
'REMOTE_USER': 'testuser'
URL-адрес /user/ можно использовать для проверки того, что вы действительно вошли в систему как testuser:
<User: testuser>
И URL-адрес /users/ теперь содержит автоматически добавленный testuser (здесь также показан пользователь admin, которого я создал при выполнении syncdb):
admin,testuser
Если вы не хотите патчить Django, просто отделите классы RemoteUserAuthBackend и RemoteUserAuthMiddleware в отдельный модуль и обратитесь к нему в настройках Django.
Кажется, это задача для пользовательского AuthenticationBackend - см. Документация Django по этой теме, на djangosnippets.org есть несколько реальных примеров такого кода (см. 1 или 2) (и это совсем не сложно).
Подклассы AuthenticationBackend должны иметь только 2 определенных метода, и их код довольно прост: один должен возвращать объект User для идентификатора пользователя, второй должен выполнять проверку учетных данных и возвращать объект User, если учетные данные действительны.
Чтобы просто поддерживать базовую аутентификацию для некоторых запросов (а не работать с веб-сервером - именно так кто-то может интерпретировать заголовок вашего вопроса), вы захотите посмотреть здесь:
Это было добавлено в выпуск Django 1.3. См. Более подробную документацию по этому поводу здесь: http://docs.djangoproject.com/en/dev/howto/auth-remote-user/
Да, вы можете использовать базовую авторизацию с django как нечто подобное:
def post(self, request):
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
token_type, _, credentials = auth_header.partition(' ')
import base64
expected = base64.b64encode(b'<username>:<password>').decode()
if token_type != 'Basic' or credentials != expected:
return HttpResponse(status=401)
authorization success flow code ...
request.META содержит ключ HTTP_AUTHORIZATION, в котором присутствует ваша авторизация.
В случае, если вы используете apache с modWSGI, ключ HTTP_AUTHORIZATION может отсутствовать. Вам нужно добавить строку ниже в конфигурацию WSGI
WSGIPassAuthorization On
Обратитесь к этому подробному ответу: Передача информации аутентификации дайджеста apache2 в сценарий wsgi, выполняемый mod_wsgi
Надеюсь, это будет полезно для тех, кто задается вопросом, почему отсутствует ключ HTTP_AUTHORIZATION.
Спасибо за это. В конце концов, я сделал то, что вы предложили, и поместил классы RemoteUserAuthBackend и RemoteUserAuthMiddleware в свой собственный модуль, на который я ссылался в settings.py, и это сработало.