Переопределить аутентификацию Django с помощью промежуточного программного обеспечения

У меня есть веб-сайт Django и форум MyBB, и я хотел бы разделить между ними аутентификацию. Мой сайт раньше был доской объявлений; затем я создал несколько других разделов в Django, и MyBB, и Django работают в одном домене. Я настроил систему, в которой при регистрации (на форуме) каждый пользователь получает двух пользователей: пользователя Django и пользователя MyBB. Пользователи используют форум для входа в систему, поэтому мне нужно, чтобы Django прочитал файлы cookie MyBB и установил соответствующую учетную запись Django в качестве зарегистрированного пользователя.

Могу ли я сделать это с помощью промежуточного программного обеспечения? Это промежуточное программное обеспечение будет читать файлы cookie MyBB (которые содержат идентификатор пользователя MyBB) и устанавливать request.user для соответствующего пользователя Django. Я новичок в Django, и я не уверен, что установка request.user (или вызов authenticate) в промежуточном программном обеспечении является хорошей идеей (или есть лучшие способы сделать это).


person pt2ph8    schedule 12.11.2012    source источник


Ответы (4)


Я думаю, что правильным будет сочетание промежуточного программного обеспечения и Серверная часть аутентификации Django.

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

class MiddlewareTracker:
 def process_request(self, request):
    id = request.COOKIES.get('logged_in_id') 
    authenticate(user_id = id)
    return None

class ForumAuthBackend(object):

    def authenticate(self, *args, **kwargs):
        id = kwargs.get('user_id')
        return User.objects.get(id = id)

    def get_user(self, user_id):
        return User.objects.get(id = user_id)

Я также рекомендую пройти через этот https://docs.djangoproject.com/en/1.2/topics/auth/

person Siddharth Sarda    schedule 12.11.2012
comment
Это не работает для меня. Вызов authenticate не имеет никакого эффекта. Я уже проверил порядок промежуточных программ и серверов аутентификации. Я также проверил, что поддержанный объект возвращает действительный объект User. - person pt2ph8; 12.11.2012
comment
Вы установили AUTHENTICATION_BACKENDS на свой сервер? Можете ли вы также объяснить, что вы подразумеваете под вызовом аутентификации, который не имеет никакого эффекта? Это вызывается? - person Siddharth Sarda; 13.11.2012
comment
Поменял на request.user = authenticate(user_id = id), теперь работает. - person pt2ph8; 13.11.2012
comment
Круто, не могли бы вы поделиться своим кодом, пожалуйста? и пометить вопрос как отвеченный. Либо мой ответ, либо опубликовать свой код в качестве ответа? - person Siddharth Sarda; 13.11.2012
comment
Почти такой же код, я просто заменил ваш вызов authenticate на request.user = authenticate(user_id = id). - person pt2ph8; 16.11.2012
comment
Кроме того, я начал вознаграждение за этот вопрос, потому что он не привлекал внимания (нет голосов/других ответов, поддерживающих ваше решение), и я хотел убедиться, что этот код хорош. maulik13, кажется, подтверждает это - подождет, пока не закончится награда, а затем, если нет лучшего ответа, вы можете получить репутацию. - person pt2ph8; 16.11.2012
comment
Извините, но кажется, что вознаграждение может быть назначено только за ответы, опубликованные после начала вознаграждения, поэтому maulik13 получает репутацию. Спасибо! - person pt2ph8; 20.11.2012

Если user_id, хранящийся в вашем файле cookie MyBB, представляет того же пользователя в базе данных Django, вы можете получить объект пользователя прямо из этого идентификатора, используя бэкэнд Django по умолчанию. Если эти идентификаторы не совпадают, вам нужен собственный бэкенд для получения пользовательского объекта Django. Чтобы получить идентификатор пользователя из файла cookie MyBB и обновить пользователя на его основе, вам необходимо иметь специальное промежуточное ПО для аутентификации.

Промежуточное ПО

Основная идея состоит в том, чтобы получить объект пользователя (на основе вашей логики аутентификации) и назначить его request.user. Вот один пример (не проверенный).

from django.contrib import auth

class MyBBMiddleware:
    def process_request(self, request):
        user_cookie_name = "session_key"
        if user_cookie_name not in request.COOKIES:
            # log user out if you want
            return 
        id = request.COOKIES.get(user_cookie_name)
        # this will find the right backend
        user = auth.authenticate(id) 
        request.user = user
        # if you want to persist this user with Django cookie do the following
        #auth.login(request, user)

Имейте в виду, что это вызывается для каждого запроса, отправленного на ваш сайт Django. Для повышения производительности вы можете кэшировать пользователя и/или использовать ленивый трюк с объектами, ПРИМЕР.

Бэкэнд

Если вам нужно написать собственную логику для извлечения объекта пользователя и аутентификации пользователя, вы можете сделать следующее.

class MyBBCookieBackend(object):
    def authenticate(self, user_id):
        return self.get_user(user_id)
    def get_user(self, user_id):
        # if user_id is not the same in Django and MyBB tables, 
        #  you need some logic to relate them and fetch Django user
        try:
            #TODO your custom logic
            user = User.objects.get(id=user_id)
            return user
        except User.DoesNotExist:
            return None

Вам нужно добавить свой собственный бэкэнд и промежуточное ПО в файл настроек сайта.

person maulik13    schedule 15.11.2012

Попробуйте разобраться с request.session. request объект является первым аргументом в поле зрения. Подробнее о сессии здесь: https://docs.djangoproject.com/en/dev/topics/http/sessions/

Вы определенно можете сделать это с помощью промежуточного программного обеспечения: больше информации о промежуточном программном обеспечении здесь: https://docs.djangoproject.com/en/dev/topics/http/middleware/

person Pol    schedule 12.11.2012

Я считаю, что лучше использовать process_view вместо process_request, так как представление процесса имеет следующую информацию:

  1. запрос
  2. Функция, которую нужно вызвать
  3. Переданные аргументы

process_view(request, view_func, view_args, view_kwargs):
    if not request.user.is_authenticated():
        return HttpResponseRedirect(settings.LOGIN_URL)
    return None

Это делает его более гибким, поскольку у нас также есть функция information(view_func). Таким образом, мы можем ограничить это некоторыми функциями, также используя:

view_func.__name_

который дает имя функции.

person Sujeet    schedule 25.04.2017