Django使用邮箱替代用户名进行用户认证失败求助
Django使用邮箱替代用户名进行用户认证失败求助
看起来你已经在尝试用邮箱替代用户名做Django认证了,但卡在了认证环节对吧?我帮你梳理下代码里的几个关键问题,应该就能解决啦!
先讲最核心的问题:自定义认证后端完全没用到邮箱!
你的backends.py里的authenticate方法现在还是在通过username参数查询用户,但你调用authenticate(request, email=email, password=password)时传的是email参数,这就导致认证逻辑根本没用到邮箱,自然匹配不到用户!
修复后的backends.py:
from django.contrib.auth.backends import ModelBackend from .models import UserRegister from django.db.models import Q class CustomAuthBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 从关键字参数中获取传入的邮箱(你调用authenticate时传的是email=xxx) user_email = kwargs.get('email', username) try: # 用邮箱查询用户(如果需要兼容用户名登录,可以加Q(username=user_email)) user = UserRegister.objects.get(email=user_email) # 验证密码(注意必须用check_password,不能直接对比明文) if user.check_password(password): return user except UserRegister.DoesNotExist: print('Unable to authenticate: 用户不存在') return None except UserRegister.MultipleObjectsReturned: # 防止出现重复邮箱(你的模型里email是unique的,这个情况基本不会发生) user = UserRegister.objects.filter(email=user_email).first() if user and user.check_password(password): return user def get_user(self, user_id): try: return UserRegister.objects.get(pk=user_id) except UserRegister.DoesNotExist: return None
第二个坑:用户模型重复定义字段导致密码明文存储!
你继承了AbstractUser,但又自己定义了password、last_login、is_active字段,而AbstractUser本身已经包含这些字段了!重复定义会导致:
- 注册时密码没有被哈希处理,直接明文存入数据库,
check_password验证必然失败 - 模型字段冲突,Django的内置认证逻辑出错
修复后的models.py:
from django.db import models from django.contrib.auth.models import AbstractUser class UserRegister(AbstractUser): # 只保留你需要扩展/重写的字段,AbstractUser已包含username、email、password、is_active等 username = models.CharField(max_length=50, unique=True, db_index=True) email = models.EmailField(unique=True) # 必须重写related_name,避免和默认User模型的groups、user_permissions冲突 groups = models.ManyToManyField( 'auth.Group', related_name='custom_user_groups', blank=True, help_text='The groups this user belongs to.' ) user_permissions = models.ManyToManyField( 'auth.Permission', related_name='custom_user_permissions', blank=True, help_text='Specific permissions for this user.' ) class Meta: verbose_name = "Custom User" verbose_name_plural = "Custom Users" def __str__(self): return self.username
第三个坑:注册视图手动创建用户时没有哈希密码!
你原来的注册逻辑直接把明文密码赋值给password字段,导致密码没有被哈希,这也是认证失败的关键原因之一。
修复后的注册视图(views.py中signup部分):
if 'signup' in request.POST: login_form = UserLoginForm() signup_form = UserSignUpForm(request.POST) if signup_form.is_valid(): # 直接用form.save(),UserCreationForm会自动处理密码哈希! user = signup_form.save() # 可选:注册成功后直接登录用户 login(request, user) messages.success(request, "注册成功并已登录!") return HttpResponseRedirect('/home') else: messages.error(request,"请修复以下错误。") print("注册表单错误:",signup_form.errors) # ... 其他错误打印代码保留
如果一定要手动创建用户,必须用set_password方法哈希密码:
form_info = UserRegister( username=signup_form.cleaned_data.get('username'), email=signup_form.cleaned_data.get('email') ) form_info.set_password(signup_form.cleaned_data.get('password1')) # 哈希密码 form_info.save()
最后必须做的配置!
在settings.py里添加以下配置,告诉Django使用你的自定义用户模型和认证后端:
# 指定自定义用户模型 AUTH_USER_MODEL = '你的app名称.UserRegister' # 比如app叫accounts,就写accounts.UserRegister # 配置自定义认证后端 AUTHENTICATION_BACKENDS = [ '你的app名称.backends.CustomAuthBackend', # 可选:保留默认后端,兼容用户名登录 # 'django.contrib.auth.backends.ModelBackend', ]
收尾:迁移数据库
修改模型后必须重新生成迁移并应用:
python manage.py makemigrations python manage.py migrate
(开发环境建议清空旧数据库重新测试,避免迁移冲突)
现在再测试登录,应该就能正常通过邮箱和密码认证啦!
备注:内容来源于stack exchange,提问作者Hardik Jain
相关产品推荐
相关产品推荐

