最兼容的方法是创建一个包含站点模型外键的用户配置文件模型,然后编写一个自定义身份验证后端,根据该 FK 的值检查当前站点。一些示例代码:
定义您的配置文件模型,例如在 app/models.py 中:
from django.db import models
from django.contrib.sites.models import Site
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
site = models.ForeignKey(Site)
编写您的自定义身份验证后端,继承自默认后端,例如在 app/auth_backend.py 中:
from django.contrib.auth.backends import ModelBackend
from django.contrib.sites.models import Site
class SiteBackend(ModelBackend):
def authenticate(self, **credentials):
user_or_none = super(SiteBackend, self).authenticate(**credentials)
if user_or_none and user_or_none.userprofile.site != Site.objects.get_current():
user_or_none = None
return user_or_none
def get_user(self, user_id):
try:
return User.objects.get(
pk=user_id, userprofile__site=Site.objects.get_current())
except User.DoesNotExist:
return None
此身份验证后端假定所有用户都有个人资料;您需要确保您的用户创建/注册过程始终创建一个。
覆盖的authenticate
方法确保用户只能登录正确的站点。get_user
每次请求时都会调用该方法,以根据用户会话中存储的身份验证信息从数据库中获取用户;我们的覆盖确保用户不能登录站点 A,然后使用相同的会话 cookie 来获得对站点 B 的未经授权的访问。(感谢 Jan Wrobel 指出需要处理后一种情况。)