Принудительная аутентификация любым пользователем

В целях отладки проекта мне понадобилось быстро просматривать сайт глазами конкретного пользователя. Для этого я решил написать отдельный view, в который передаю id пользователя. В документации Django написано, что для авторизации пользователя нужно сначала выполнить фунцию authenticate из модуля django.contrib.auth, а затем login.

authenticate занимается тем, что по очереди до первого успеха опрашивает все доступные бэкенды аутентификации, перечисленные в settings.AUTHENTICATION_BACKENDS, передавая им параметры собственного вызова. В случае успеха backend должен вернуть объект типа django.contrib.auth.User.models, в противном случае None.

login получает в параметрах request и user и синхронизирует request.user и user, в зависимости от того, что из них является None.

Трудность заключается в том, что стандартный backend аутентификации Django, принимает в качестве параметров имя пользователя и незашифрованный пароль. Незашифрованные пароли пользователей мне неизвестны. Пришлось отказаться от функции authenticate и передавать в login пользователя полученного непосредственно по запросу User.objects.get(pk=user_id).

Однако, после такого финта, Django стал возмущаться на то, что у объекта пользователя передаваемого в функцию login нет атрибута backend, в который функция authenticate (которую я не вызываю) должна была записать имя успешно сработавшего бэкенда аутентификации.

Мне помогло прописывание стандартного бэкенда. Таким образом код приобрёл следующую форму:


def loginas(request,user_id):
if not getattr(settings,'LOGIN_DEBUG',False):
raise AccessDeniedException('/')
else:
user = User.objects.get(pk=user_id)
user.backend = 'django.contrib.auth.backends.ModelBackend'
auth.login(request, user)
return HttpResponseRedirect(user.get_profile().get_absolute_url())
e

def loginas(request,user_id):
if not getattr(settings,’LOGIN_DEBUG’,False):
raise AccessDeniedException(‘/’)
else:
user = User.objects.get(pk=user_id)
user.backend = ‘django.contrib.auth.backends.ModelBackend’
auth.login(request, user)
return HttpResponseRedirect(user.get_profile().get_absolute_url())
e


C помощью опции settings.LOGIN_DEBUG можно быстро отлючать/включать отладочную функцию логина.

Ну, и в завершение я чуть-чуть изменил свой inclusion tag, который использую в шаблонах для отображения ссылки на переданный объект. Теперь этот тэг выводит звёздочку рядом с именем пользователя, которая является ссылкой на вышеописанный view.

Собственно, вот сам код тэга:


@register.inclusion_tag('site/link.html')
def link(object,base=u''):
user_id = None
if isinstance(object,User):
object = object.get_profile()
if isinstance(object,UserProfile):
if getattr(settings,'LOGIN_DEBUG',False):
user_id = object.user.id
url = object.get_absolute_url()
url = base + url
anchor = smart_unicode(object)
return {
'user_id': user_id,
'url': url,
'anchor': anchor}

@register.inclusion_tag(‘site/link.html’)
def link(object,base=u”):
user_id = None
if isinstance(object,User):
object = object.get_profile()
if isinstance(object,UserProfile):
if getattr(settings,’LOGIN_DEBUG’,False):
user_id = object.user.id
url = object.get_absolute_url()
url = base + url
anchor = smart_unicode(object)
return {
‘user_id’: user_id,
‘url’: url,
‘anchor’: anchor}

и шаблон:


<a href="{{ url }}">{{ anchor|escape }}</a>
{% if user_id %}
<a href="/debug/loginas/{{ user_id }}/">*</a>
{% endif %}

<a href=”{{ url }}”>{{ anchor|escape }}</a>
{% if user_id %}
<a href=”/debug/loginas/{{ user_id }}/”>*</a>
{% endif %}


UPD:
А вот реализация для middleware, здесь ID пользователя, которым нужно залогиниться, передаётся просто через GET-параметр loginas


from django.http import HttpResponseRedirect
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import login

class DebugLoginMiddleware(object):
def process_request(self, request):
if not getattr(settings,'LOGIN_DEBUG',False):
return None
try:
id = int(request.GET.get('loginas',0))
except ValueError:
return None
try:
user = User.objects.get(pk=id)
except User.DoesNotExist:
return None
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return None

from django.http import HttpResponseRedirect
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import login

class DebugLoginMiddleware(object):
def process_request(self, request):
if not getattr(settings,’LOGIN_DEBUG’,False):
return None
try:
id = int(request.GET.get(‘loginas’,0))
except ValueError:
return None
try:
user = User.objects.get(pk=id)
except User.DoesNotExist:
return None
user.backend = ‘django.contrib.auth.backends.ModelBackend’
login(request, user)
return None
Add post to:   Google Slashdot Yahoo Digg Technorati Delicious Bobrdobr.ru Newsland.ru Smi2.ru Rumarkz.ru Vaau.ru Memori.ru Rucity.com Moemesto.ru News2.ru Mister-Wong.ru Yandex.ru Myscoop.ru 100zakladok.ru
Make comment

Comments

No comments for this post
comment submission form

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image