使用中间件覆盖Django身份验证
我有一个Django网站和一个MyBB论坛,我想在它们之间共享身份验证。我的网站曾经是一个留言板;然后我在Django中构建了其他几个部分,MyBB和Django都运行在同一个域上。我建立了一个系统,在论坛上注册后,每个用户都有两个用户:一个Django用户和一个MyBB用户。用户使用论坛登录,因此我需要Django读取MyBB的cookies,并将相应的Django帐户设置为登录用户使用中间件覆盖Django身份验证,django,authentication,django-middleware,Django,Authentication,Django Middleware,我有一个Django网站和一个MyBB论坛,我想在它们之间共享身份验证。我的网站曾经是一个留言板;然后我在Django中构建了其他几个部分,MyBB和Django都运行在同一个域上。我建立了一个系统,在论坛上注册后,每个用户都有两个用户:一个Django用户和一个MyBB用户。用户使用论坛登录,因此我需要Django读取MyBB的cookies,并将相应的Django帐户设置为登录用户 我可以用中间件来做吗?该中间件将读取MyBB的cookies(其中包含MyBB用户的id),并将request
我可以用中间件来做吗?该中间件将读取MyBB的cookies(其中包含MyBB用户的id),并将
request.user
设置为相应的Django用户。我是Django新手,我不确定在中间件中设置request.user
(或调用authenticate
)是否是个好主意(或者是否有更好的方法) 尝试处理请求。会话
<代码>请求对象作为视图中的第一个参数出现。有关会话的更多详细信息,请参见此处:
您完全可以使用中间件实现这一点:有关中间件的更多信息,请点击此处:我认为,中间件和中间件的组合是正确的选择 中间件将调用后端的
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)
我还建议您仔细检查一下如果MyBB cookie中存储的用户id代表Django数据库中的同一用户,那么您可以使用默认Django后端直接从该id获取用户对象。如果这些ID不匹配,则需要自定义后端来获取Django用户对象。 要从MyBB cookie获取用户ID并基于它更新用户,您需要有一个自定义的身份验证中间件 中间件 其主要思想是获取用户对象(基于您的身份验证逻辑)并将其分配给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
您需要在站点设置文件中添加自定义后端和中间件。我认为最好使用
process\u view
而不是process\u request
,因为process view具有以下信息:
这使得它更加灵活,因为我们还有函数
信息(view\u func)
。
因此,我们也可以使用以下方法将其限制为某些函数:
view_func.__name_
它给出了函数名。这对我不起作用。
authenticate
调用无效。我已经检查了中间件和授权后端的顺序。我还检查了备份是否返回了有效的用户
对象。是否设置了身份验证?后端是否设置为后端?你能解释一下你所说的认证调用无效是什么意思吗?正在调用它吗?更改为request.user=authenticate(user\u id=id)
,现在它可以工作了。酷,你能分享你的代码吗?并将问题标记为已回答。要么是我的答案,要么把你的代码作为你的答案张贴出来?几乎是同样的代码,我只是用request.user=authenticate(user\u id=id)
替换了你的authenticate
呼叫。
process_view(request, view_func, view_args, view_kwargs):
if not request.user.is_authenticated():
return HttpResponseRedirect(settings.LOGIN_URL)
return None
view_func.__name_