Django中非User模型的特殊用户如何实现认证与登录
Django多用户模型(自定义特殊用户)认证登录方案
1. 非默认User模型能否调用系统自带认证函数
Django自带的authenticate()、login()函数默认仅适配继承了AbstractBaseUser的用户模型:
- 如果你自定义的特殊用户模型未继承Django提供的基础用户抽象类,不能直接调用这两个函数
- 如果自定义模型继承了
AbstractBaseUser或AbstractUser,只要配置对应认证后端,即可正常调用系统自带认证函数
2. 特殊用户的身份认证与登录实现方案
方案1:配置专属认证后端,复用系统自带认证函数
- 先保证自定义特殊用户模型继承
AbstractBaseUser,定义好USERNAME_FIELD等必要字段,密码存储使用Django自带的set_password()方法加密 - 自定义认证后端类,重写校验逻辑,示例代码如下:
from django.contrib.auth.backends import BaseBackend from .models import SpecialUser from django.contrib.auth.models import User class CustomUserAuthBackend(BaseBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 可通过请求参数标识区分普通用户/特殊用户 is_special = kwargs.get('is_special', request.POST.get('is_special', False)) if is_special: try: user = SpecialUser.objects.get(username=username) if user.check_password(password): return user except SpecialUser.DoesNotExist: return None else: # 走默认普通用户校验逻辑 try: user = User.objects.get(username=username) if user.check_password(password): return user except User.DoesNotExist: return None def get_user(self, user_id): # 兼容两种用户模型的查询逻辑 try: return User.objects.get(pk=user_id) except User.DoesNotExist: try: return SpecialUser.objects.get(pk=user_id) except SpecialUser.DoesNotExist: return None
- 在
settings.py中注册自定义认证后端:
AUTHENTICATION_BACKENDS = [ '你的应用路径.CustomUserAuthBackend', ]
- 认证登录调用逻辑:
# 特殊用户认证 user = authenticate(request, username=账号, password=密码, is_special=True) if user is not None: login(request, user) # 直接调用系统login方法完成登录
方案2:不使用login()函数,手动实现登录逻辑
完全支持跳过系统login()函数实现登录,手动写入session即可达到相同效果,示例代码如下:
# 手动校验特殊用户的账号密码逻辑略 user = SpecialUser.objects.get(username=账号) if user.check_password(密码): # 手动写入session,和系统login效果完全一致 request.session['_auth_user_id'] = user.pk request.session['_auth_user_backend'] = '你的应用路径.CustomUserAuthBackend' # 可选配置session过期时间,0代表浏览器关闭即失效 request.session.set_expiry(0)
配置完成后,后续请求的request.user会自动读取到对应的特殊用户实例。
3. 注意事项
- 若你的自定义特殊用户模型完全不继承
AbstractBaseUser,需要额外自定义中间件,从session中读取用户ID后手动查询对应模型赋值给request.user - 多用户模型场景建议用UUID作为主键,避免不同模型的相同数值ID导致用户查询错误
- 密码不要明文存储,必须使用Django自带的
set_password()、check_password()处理密码的加密和校验
内容的提问来源于stack exchange,提问作者nsb
相关产品推荐
相关产品推荐

