You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 16:35:23