Django自定义用户模型与认证功能失效问题求助
Django自定义用户模型认证故障排查
问题背景
我是Django初学者,当前项目不需要is_staff、is_superuser、is_admin字段,因此自定义了用户模型,但认证功能无法正常工作。使用的是遗留数据库,通过python manage.py inspectdb生成模型,未修改字段名与表名,可接受通过Shell创建用户。
相关配置与代码
settings.py
AUTH_USER_MODEL = 'accounts.Usermanagement' AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'accounts.backends.EmailAuthBackend', ]
backends.py
#backends.py # from django.contrib.auth.models import User from django.contrib.auth.hashers import check_password from django.contrib.auth import get_user_model Usermanagement = get_user_model() class EmailAuthBackend: def authenticate(self,request,username=None,password=None): print(request) try: user = Usermanagement.objects.get(emailid=username) print(password) print(user.password) # print(check_password(password)) # print(user.check_password(password)) if user.check_password(password): return user return None except user.DoesNotExist: return None def get_user(self,user_id): try: return user.objects.get(pk=user_id) except user.DoesNotExist: return None
views.py
# views.py def loginPage(request): # POST if request.method == 'POST': form = AuthenticationForm(request,data=request.POST) # loginPage.html中邮箱输入框name属性为username,密码输入框name属性为password if form.is_valid(): # 表单验证通过 email = request.POST['username'] password = request.POST['password'] # 调试输出 print("EMAIL: ",email) print("PASSWORD: ",password) # 用户认证 user = authenticate(request,username=email,password=password) print("Authenticated ",user) # 调试输出 print(user) if user is not None: # 找到用户 login(request,user,backend='accounts.backends.EmailAuthBackend') messages.info(request, f"你已登录,当前账号:{email}") return redirect("home") else: # 未找到用户 messages.error(request,"用户不存在") return HttpResponse("用户不存在,无法登录") else: # 表单验证失败 messages.error(request,"用户名或密码无效") return HttpResponse("表单无效") # GET else: form = AuthenticationForm() context = {"form":form} return render(request,"loginPage.html",context=context)
遇到的问题
check_password始终返回False- 数据库中存储的是明文密码(例如:password=admin)
- loginPage.html中邮箱输入框name属性为username,密码输入框name属性为password
故障排查与解决方案
1. 明文密码导致验证失败
Django的check_password方法仅支持验证哈希加密后的密码字符串,数据库中存储明文必然导致验证失败。解决方式:
- 通过Shell创建用户时,必须调用
set_password()方法生成哈希密码,而非直接赋值:from accounts.models import Usermanagement user = Usermanagement(emailid='test@example.com') user.set_password('admin') # 自动哈希加密 user.save() - 遗留数据库中的现有明文密码,可编写批量更新脚本,遍历用户调用
set_password()后保存。
2. 认证后端代码错误
EmailAuthBackend存在两处语法错误:
except user.DoesNotExist:应改为except Usermanagement.DoesNotExist:(局部变量user无法调用DoesNotExist异常)get_user方法中return user.objects.get(pk=user_id)应改为return Usermanagement.objects.get(pk=user_id)
修正后的backends.py:
#backends.py from django.contrib.auth import get_user_model Usermanagement = get_user_model() class EmailAuthBackend: def authenticate(self, request, username=None, password=None): try: user = Usermanagement.objects.get(emailid=username) if user.check_password(password): return user return None except Usermanagement.DoesNotExist: return None def get_user(self, user_id): try: return Usermanagement.objects.get(pk=user_id) except Usermanagement.DoesNotExist: return None
3. 自定义用户模型合规性检查
确保Usermanagement模型满足Django自定义用户模型的核心要求:
- 继承
AbstractBaseUser(无需默认字段时优先选择) - 指定
USERNAME_FIELD = 'emailid'(将邮箱作为登录标识) - 实现
UserManager类,提供create_user和create_superuser方法
示例适配模型:
# accounts/models.py from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.db import models class UserManager(BaseUserManager): def create_user(self, emailid, password=None): if not emailid: raise ValueError('用户必须提供邮箱') user = self.model(emailid=emailid) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, emailid, password): user = self.create_user(emailid, password) user.save(using=self._db) return user class Usermanagement(AbstractBaseUser): emailid = models.EmailField(unique=True) # 你的其他遗留字段 is_active = models.BooleanField(default=True) # 建议保留,用于控制用户状态 objects = UserManager() USERNAME_FIELD = 'emailid' def __str__(self): return self.emailid
4. 登录表单优化
默认AuthenticationForm验证的是username字段,与你的emailid不匹配,可自定义登录表单适配:
# accounts/forms.py from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth import get_user_model Usermanagement = get_user_model() class EmailAuthenticationForm(AuthenticationForm): class Meta: model = Usermanagement fields = ('emailid', 'password')
在views.py中替换为自定义表单即可。
内容的提问来源于stack exchange,提问作者Nipun
相关产品推荐
相关产品推荐

