用中间件覆盖Django身份验证

pt2*_*ph8 7 authentication django django-middleware

我有一个Django网站和一个MyBB论坛,我想在他们之间共享身份验证.我的网站曾经是留言板; 然后我在Django中构建了一些其他部分,MyBB和Django都运行在同一个域中.我已经建立了一个系统,在注册时(在论坛上)每个用户都有两个用户:一个Django用户和一个MyBB用户.用户使用论坛登录,因此我需要Django来读取MyBB的cookie并将相应的Django帐户设置为登录用户.

我可以用中间件做到吗?该中间件将读取MyBB的cookie(其中包含MyBB用户的id)并设置request.user为相应的Django用户.我是Django的新手,我不确定在中间件中设置request.user(或调用authenticate)是一个好主意(或者是否有更好的方法).

mau*_*k13 6

如果存储在MyBB cookie中的user_id代表Django数据库中的同一用户,那么您可以使用默认的Django后端直接从该id获取用户对象.如果这些ID不匹配,则需要自定义后端来获取Django用户对象.要从MyBB cookie获取用户ID并根据它更新用户,您需要拥有自定义身份验证中间件.

中间件

主要思想是获取用户对象(基于您的身份验证逻辑)并将其分配给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)
Run Code Online (Sandbox Code Playgroud)

请记住,每次发送到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
Run Code Online (Sandbox Code Playgroud)

您需要在站点设置文件中添加自定义后端和中间件.


小智 5

我认为正确的做法是将中间件和Django 身份验证后端结合起来。

您的中间件将authenticate()使用可能的用户 ID 作为关键字参数调用后端。您的身份验证后端将依次调用相应的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)
Run Code Online (Sandbox Code Playgroud)

我还将建议浏览此https://docs.djangoproject.com/en/1.2/topics/auth/