Django AuthenticationForm校验不通过 非超级用户无法登录问题
问题根因
核心故障点在自定义注册表单UserCreateForm的save方法,super()调用参数错误,直接跳过了UserCreationForm内置的密码哈希逻辑:
- 代码中
super(UserCreationForm, self).save(commit=False)的写法,会直接调用UserCreationForm的父类ModelForm的save方法,该方法仅处理模型原生字段,不会识别password1/password2这类表单自定义字段,也不会执行密码哈希操作,最终导致通过注册页面创建的普通用户,数据库中存储的密码为空或未哈希明文,完全不符合Django的密码校验规则。 - 超级用户通过
python manage.py createsuperuser命令创建,密码会被自动哈希存储,因此可以正常通过登录校验;普通注册用户密码存储不符合规范,登录时AuthenticationForm调用认证后端校验密码失败,会直接抛出“Please enter a correct username and password”错误,无法进入form.is_valid()的通过分支。
代码中还存在两处不规范问题:
- 注册视图GET分支写为
form=UserCreateForm,未加括号实例化,传递给模板的是表单类而非实例,会引发表单渲染异常。 - 登录视图中
AuthenticationForm校验通过后又手动调用一次authenticate()属于冗余逻辑,AuthenticationForm在校验阶段已经完成了用户认证流程,可直接获取已认证的用户对象。
修复方案
- 修正
UserCreateForm中super()的调用参数,确保正确调用父类UserCreationForm的save方法,自动完成密码哈希。 - 修正注册视图GET分支的表单实例化语法。
- 移除登录视图中的冗余认证逻辑,简化代码。
修正后的完整代码
def log_in(request): if request.method == "POST": form = AuthenticationForm(request, data=request.POST) if form.is_valid(): # AuthenticationForm校验通过后可直接获取已认证用户,无需重复调用authenticate user = form.get_user() login(request, user) messages.info(request, 'You have successfully logged in!') return redirect('news') else: messages.error(request, 'Invalid username or password!') else: # GET请求初始化空表单 form = AuthenticationForm() return render(request, 'post/login.html', {'form': form}) def register_user(request): if request.method == 'POST': form = UserCreateForm(request.POST) if form.is_valid(): user = form.save() login(request, user) messages.success(request, 'Registration was successful') return redirect('news') messages.error(request, 'Try again!') else: # GET请求实例化空表单,必须加括号 form = UserCreateForm() return render(request, 'post/register.html', {'form': form}) class UserCreateForm(UserCreationForm): email = forms.EmailField(required=True) class Meta: model = User fields = ['username', 'email', 'password1', 'password2'] def save(self, commit=True): # 修正super第一个参数为当前类名,正确调用UserCreationForm的save逻辑完成密码哈希 user = super(UserCreateForm, self).save(commit=False) user.email = self.cleaned_data.get('email') if commit: user.save() return user
注意:代码修复前已经注册的普通用户,因为密码存储格式错误无法自动修复,需要重新注册后才能正常登录。
内容的提问来源于stack exchange,提问作者diyara
相关产品推荐
相关产品推荐

