如何在Django中限制用户仅访问所属站点?
限制Django用户仅访问所属站点的实现方案
1. 扩展用户模型,关联站点
首先需要给用户模型添加与Django内置Site模型的关联,让每个用户归属到特定站点。通过继承AbstractUser扩展模型:
from django.contrib.auth.models import AbstractUser from django.contrib.sites.models import Site from django.db import models class CustomUser(AbstractUser): # 关联用户所属的站点,外键支持用户归属单个站点 site = models.ForeignKey(Site, on_delete=models.CASCADE, related_name='site_users')
之后在项目settings.py中配置自定义用户模型:
AUTH_USER_MODEL = 'your_app_name.CustomUser'
2. 自定义认证后端,拦截跨站点登录
编写自定义认证后端,在用户登录时验证其所属站点是否与当前访问的站点一致:
from django.contrib.auth.backends import ModelBackend from django.contrib.sites.shortcuts import get_current_site from .models import CustomUser class SiteRestrictedAuthBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 无请求对象时直接返回None if not request: return None current_site = get_current_site(request) try: # 仅查找属于当前站点的用户 user = CustomUser.objects.get(username=username, site=current_site) # 验证密码 if user.check_password(password): return user except CustomUser.DoesNotExist: # 无匹配用户时返回None,保持默认登录失败提示 return None
将自定义后端配置到settings.py:
AUTHENTICATION_BACKENDS = [ 'your_app_name.backends.SiteRestrictedAuthBackend', ]
3. 添加中间件,防止已登录用户跨站点访问
即使用户已登录,若尝试访问其他站点,需强制登出或拒绝访问。编写中间件:
from django.contrib.auth import logout from django.contrib.sites.shortcuts import get_current_site from django.http import HttpResponseForbidden class SiteAccessControlMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if request.user.is_authenticated: current_site = get_current_site(request) # 检查用户所属站点是否与当前站点匹配 if request.user.site != current_site: logout(request) return HttpResponseForbidden("您无权访问该站点") response = self.get_response(request) return response
在settings.py的MIDDLEWARE列表中添加该中间件,注意需放在django.contrib.auth.middleware.AuthenticationMiddleware之后:
MIDDLEWARE = [ # ... 其他中间件 'django.contrib.auth.middleware.AuthenticationMiddleware', 'your_app_name.middleware.SiteAccessControlMiddleware', # ... 其他中间件 ]
4. 注册用户时自动关联当前站点
在用户注册流程中,自动将当前访问的站点关联到新创建的用户:
from django.contrib.sites.shortcuts import get_current_site from django.views.generic.edit import CreateView from .forms import CustomUserCreationForm from django.urls import reverse_lazy class SignUpView(CreateView): form_class = CustomUserCreationForm template_name = 'auth/signup.html' success_url = reverse_lazy('login') def form_valid(self, form): current_site = get_current_site(self.request) user = form.save(commit=False) user.site = current_site user.save() return super().form_valid(form)
内容的提问来源于stack exchange,提问作者JasonTS
相关产品推荐
相关产品推荐

