Django密码重置表单无法生效,求问题排查与解决方案
密码重置表单不生效问题排查与修复
核心问题分析
你的密码重置流程存在三个关键漏洞,导致表单提交后密码未修改:
1. 生成重置token后未保存到用户记录
在forgot_password视图中,生成了UUID token但未将其赋值给用户的forget_password_token字段,也没有保存用户对象。这会导致后续通过token查找用户时无法匹配,同时密码重置页面的user_id也无法正确传递。
2. 密码重置视图缺少修改密码的核心逻辑
ChangePassword视图在验证密码一致性后,直接跳转到登录页,完全没有执行更新用户密码的操作,也没有清理已使用的token。
3. 用户对象访问逻辑错误
你的User模型直接继承AbstractUser,profile_obj本身就是用户实例,不需要通过profile_obj.user.id获取用户ID,直接使用profile_obj.id即可。同时未处理profile_obj为None的情况(比如token无效时),会引发异常。
修复后的完整代码
1. 修复views.py中的forgot_password函数
def forgot_password(request): try: if request.method == 'POST': email = request.POST.get('email') user_obj = User.objects.filter(email=email).first() if not user_obj: messages.warning(request, '未找到该邮箱对应的用户。') return redirect('forgot_password') # 生成并保存token到用户记录 token = str(uuid.uuid4()) user_obj.forget_password_token = token user_obj.save() send_forget_password_mail(user_obj.email, token) messages.success(request, '重置链接已发送至你的邮箱。') return redirect('forgot_password') except Exception as e: print(e) return render(request,'forgot.html')
2. 修复views.py中的ChangePassword函数
def ChangePassword(request, token): context = {} try: # 通过token查找用户 user_obj = User.objects.filter(forget_password_token=token).first() if not user_obj: messages.warning(request, '无效的重置链接,请重新申请。') return redirect('forgot_password') if request.method == 'POST': new_password = request.POST.get('new_password') confirm_password = request.POST.get('reconfirm_password') user_id = request.POST.get('user_id') if not user_id or int(user_id) != user_obj.id: messages.warning(request, '用户信息验证失败。') return redirect(f'/changepassword/{token}/') if new_password != confirm_password: messages.warning(request, '两次输入的密码不一致。') return redirect(f'/changepassword/{token}/') # 设置新密码并清理token user_obj.set_password(new_password) user_obj.forget_password_token = None # 重置后清空token,防止重复使用 user_obj.save() messages.success(request, '密码重置成功,请登录。') return redirect('login_user') context = {'user_id': user_obj.id} except Exception as e: print(e) messages.error(request, '重置过程中出现错误,请重试。') return redirect('forgot_password') return render(request, 'new_password.html', context)
3. 模板与模型无需修改
new_password.html、forgot.html和models.py的代码逻辑是正确的,无需调整。
关键修复点说明
- 保存token:生成token后必须调用
user_obj.save()将其写入数据库,否则无法通过token定位用户。 - 修改密码:使用
user_obj.set_password(new_password)而非直接赋值user_obj.password,因为Django需要对密码进行哈希加密存储。 - 清理token:密码重置成功后清空
forget_password_token,避免同一链接被重复使用,提升安全性。 - 异常处理:增加对无效token的判断,避免因token错误导致的页面崩溃,同时给用户明确的提示信息。
内容的提问来源于stack exchange,提问作者Mossaddak
相关产品推荐
相关产品推荐

