Django用户登录功能异常:正确凭证仍提示无效
Django登录失败:输入正确凭证仍提示无效的问题解决
你的登录失败问题根源在signup视图的密码处理逻辑错误,同时登录验证逻辑也存在匹配问题,具体问题和修复方案如下:
核心问题分析
重复哈希密码导致验证失败
User.objects.create_user()方法会自动对传入的password参数进行哈希处理并存储,但你在创建用户后又调用了user.set_password(password),这会再次对原密码进行哈希,覆盖了正确的哈希值。最终数据库里存储的是二次哈希后的密码,登录时用原密码自然无法匹配。登录时参数不匹配
默认Django的authenticate()函数是根据username字段验证身份,但你注册时username和email是独立字段,登录时却把email传给了username参数,默认情况下无法找到对应用户。
修正后的代码
修复signup视图(解决密码哈希问题)
from django.db.models import Q from django.contrib.auth.models import User from django.contrib.auth import authenticate, login from django.shortcuts import render def signup(request): if request.method == 'POST': username = request.POST['username'] email = request.POST['email'] password = request.POST['password'] confirm_password = request.POST['confirm_password'] # 检查用户是否已存在 if User.objects.filter(Q(username=username) | Q(email=email)).exists(): return render(request, 'user_auth/signup.html', {'error_message': '用户名或邮箱已存在!'}) # 检查密码是否匹配 if password != confirm_password: return render(request, 'user_auth/signup.html', {'error_message': '两次输入的密码不一致!'}) # create_user已自动处理密码哈希,无需额外调用set_password user = User.objects.create_user(username=username, email=email, password=password) return render(request, 'user_auth/signin.html') else: return render(request, 'user_auth/signup.html')
修复signin视图(两种可选方案)
方案1:临时适配——通过邮箱找用户再验证
def signin(request): if request.method == 'POST': email = request.POST['email'] password = request.POST['password'] try: # 先通过邮箱定位用户 user = User.objects.get(email=email) # 用用户的真实username做认证 user = authenticate(request, username=user.username, password=password) if user is not None: login(request, user) return render(request, 'user_auth/main.html') except User.DoesNotExist: pass return render(request, 'user_auth/signin.html', {'context': '邮箱和/或密码无效!'}) return render(request, 'user_auth/signin.html')
方案2:长期优化——允许邮箱直接登录
如果希望用户可以直接用邮箱登录,推荐配置自定义认证后端:
- 在你的app下创建
backends.py文件:
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User from django.db.models import Q class EmailBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: # 支持用户名或邮箱登录 user = User.objects.get(Q(username=username) | Q(email=username)) if user.check_password(password): return user except User.DoesNotExist: return None
- 在项目
settings.py中添加配置:
AUTHENTICATION_BACKENDS = [ '你的app名称.backends.EmailBackend', 'django.contrib.auth.backends.ModelBackend', # 保留默认用户名登录支持 ]
- 此时signin视图可以保持原写法,无需修改:
def signin(request): if request.method == 'POST': email = request.POST['email'] password = request.POST['password'] user = authenticate(request, username=email, password=password) if user is not None: login(request, user) return render(request, 'user_auth/main.html') else: return render(request, 'user_auth/signin.html', {'context': '邮箱和/或密码无效!'}) return render(request, 'user_auth/signin.html')
内容的提问来源于stack exchange,提问作者Mohammad Al Weis
相关产品推荐
相关产品推荐

