我有一个Django网站和一个MyBB论坛,我想在他们之间共享身份验证。我的网站曾经是留言板;然后我在Django中构建了一些其他部分,MyBB和Django都运行在同一个域中。我已经建立了一个系统,在注册时(在论坛上)每个用户都有两个用户:一个Django用户和一个MyBB用户。用户使用论坛登录,因此我需要Django来读取MyBB的cookie并将相应的Django帐户设置为登录用户。
我可以用中间件做到吗?该中间件将读取MyBB的cookie(其中包含MyBB用户的id)并将request.user
设置为相应的Django用户。我是Django的新手,我不确定在中间件中设置request.user
(或调用authenticate
)是个好主意(或者是否有更好的方法)。
答案 0 :(得分: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)
请记住,每次发送到Django站点的请求都会调用此方法。为了提高性能,您可以缓存用户和/或执行惰性对象技巧EXAMPLE。
<强>后端强>
如果您需要编写自己的逻辑来获取用户对象并验证用户,您可以执行以下操作。
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
您需要在站点设置文件中添加自定义后端和中间件。
答案 1 :(得分:4)
我认为正确的做法是将中间件和Django authentication backend组合在一起。
您的中间件将使用用户ID作为关键字参数调用后端的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)
答案 2 :(得分:0)
尝试处理request.session
。 request
对象作为视图中的第一个参数出现。有关会话的更多详细信息:https://docs.djangoproject.com/en/dev/topics/http/sessions/
您绝对可以使用中间件:有关中间件的更多信息,请访问:https://docs.djangoproject.com/en/dev/topics/http/middleware/
答案 3 :(得分:0)
我认为使用process_view
代替process_request
会更好,因为流程视图具有以下信息:
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_
给出了函数名称。