Django自定义邮箱用户登录时authenticate返回None问题排查
问题根源及修复方案
你的代码存在几个关键错误,导致authenticate返回None:
1. 登录时错误加密用户输入的密码
在LoginView的form_valid方法中,你对用户输入的明文密码再次调用make_password加密,然后传给authenticate。但user.check_password()方法需要接收明文密码,与数据库中已存储的加密密码进行比对,这会导致密码永远不匹配。
修复LoginView:
class LoginView(FormView): template_name = 'login.html' form_class = LoginForm def form_valid(self, form): email = form.cleaned_data['email'] # 直接使用明文密码,不要加密 password = form.cleaned_data['password'] print(email, password) # 调用authenticate时传入email参数(匹配你的后端定义) user = authenticate(request=self.request, email=email, password=password) print(user) if user is not None: print('do') login(self.request, user) return redirect('home') else: messages.info(self.request, 'invalid username or password') return redirect('login')
2. 注册时手动处理密码的方式错误
在SignUp视图中,你手动调用make_password处理密码,并且直接实例化User对象保存,这种方式不符合Django用户创建的规范,同时调用authenticate时传入了加密后的密码,导致验证失败。
修复SignUpView:
UserCreationForm的save()方法会自动处理密码加密和用户创建,无需手动操作:
class SignUp(CreateView): form_class = SignUpForm template_name = 'signup.html' def form_valid(self, form): # 直接保存表单,自动处理密码加密 user = form.save() print("User created!") # 用明文密码调用authenticate user = authenticate(request=self.request, email=user.email, password=form.cleaned_data['password1']) login(self.request, user) return redirect('home')
3. 自定义认证后端的参数兼容性优化
当前你的EmailBackend只接收email参数,但Django的authenticate有时会传入username参数(比如admin后台登录),可以优化后端使其兼容两种参数:
class EmailBackend(ModelBackend): def authenticate(self, request, username=None, password=None, email=None, **kwargs): UserModel = get_user_model() # 优先使用email参数,没有则用username(因为USERNAME_FIELD是email) login_email = email or username try: user = UserModel.objects.get(email=login_email) except UserModel.DoesNotExist: return None else: if user.check_password(password): return user return None
额外优化:LoginForm字段类型修正
你的LoginForm中email字段用了forms.CharField,应该改为forms.EmailField以确保邮箱格式验证:
class LoginForm(forms.Form): # 改为EmailField email = forms.EmailField(widget=forms.EmailInput( attrs={'class' : 'form-control', 'type' : "text", 'placeholder': "Email"})) # 其余代码不变...
完成以上修复后,authenticate应该能正确返回用户对象,登录功能即可正常工作。
内容的提问来源于stack exchange,提问作者Omnia Osman
相关产品推荐
相关产品推荐

