Переопределение аутентификации Django с промежуточным по

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

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

4 ответов


Я думаю, что правильным будет сочетание middleware и A Django аутентификации бэкэнд.

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

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/


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

промежуточное

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

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

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


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

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


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

  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_

что дает имя функции.