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

Django中如何通过绑定手机号实现用户密码重置?

Django 通过手机号重置用户密码实现方案

1. 先修正模型字段约束

首先需要给UserProfile的mobile字段增加唯一约束,避免多个账号绑定同一个手机号,修改后的models.py代码如下:

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    # 增加unique约束,blank和null根据你的业务需求保留
    mobile = models.CharField(max_length=15, blank=True, null=True, unique=True)

    def __str__(self):
        return self.user.username

修改完成后执行python manage.py makemigrations和python manage.py migrate完成数据库迁移。

2. 实现重置全流程

完整流程分为三个环节:提交手机号发送验证码、验证验证码获取重置凭证、提交新密码完成重置。

2.1 发送验证码接口逻辑

  • 前端传入用户输入的手机号
  • 后端查询UserProfile表中是否存在该手机号对应的账号(为了防撞库,无论是否存在都统一返回“如果该手机号已绑定账号,验证码将在5分钟内发送”)
  • 如果账号存在,生成6位数字验证码,存入缓存(如Redis、Django Session)并设置5分钟有效期
  • 调用短信服务商的接口将验证码发送到对应手机号

示例代码(基于FBV):

from django.core.cache import cache
from django.http import JsonResponse
import random
from .models import UserProfile

def send_reset_code(request):
    mobile = request.POST.get("mobile")
    if not mobile:
        return JsonResponse({"code": 400, "msg": "请输入手机号"})
    # 检查手机号是否存在
    try:
        UserProfile.objects.get(mobile=mobile)
    except UserProfile.DoesNotExist:
        return JsonResponse({"code": 200, "msg": "如果该手机号已绑定账号,验证码将在5分钟内发送"})
    # 生成验证码
    code = random.randint(100000, 999999)
    # 存入缓存,key用手机号做唯一标识,有效期300秒
    cache.set(f"reset_code_{mobile}", code, timeout=300)
    # 这里调用你的短信发送接口发送code到mobile
    # send_sms(mobile, code)
    return JsonResponse({"code": 200, "msg": "验证码已发送"})

2.2 验证码校验接口逻辑

  • 前端传入手机号和用户填写的验证码
  • 后端从缓存中取出对应手机号的验证码,判断是否和传入的一致
  • 校验通过后,用Django自带的signing模块生成带过期时间的重置token,返回给前端作为后续重置密码的凭证

示例代码:

from django.core import signing
from django.core.cache import cache
from django.http import JsonResponse

def verify_reset_code(request):
    mobile = request.POST.get("mobile")
    input_code = request.POST.get("code")
    if not all([mobile, input_code]):
        return JsonResponse({"code": 400, "msg": "参数不全"})
    cache_code = cache.get(f"reset_code_{mobile}")
    if not cache_code or str(cache_code) != str(input_code):
        return JsonResponse({"code": 400, "msg": "验证码错误或已过期"})
    # 生成有效期15分钟的重置token
    token = signing.dumps({"mobile": mobile}, salt="reset_pwd_salt", expires_in=900)
    return JsonResponse({"code": 200, "msg": "验证通过", "reset_token": token})

2.3 密码重置接口逻辑

  • 前端传入重置token、新密码
  • 后端校验token是否有效,解析出对应的手机号
  • 查询到对应用户后,调用Django自带的set_password()方法修改密码
  • 清空缓存中对应的验证码,完成重置

示例代码:

from django.core import signing
from django.http import JsonResponse
from .models import UserProfile

def reset_password(request):
    reset_token = request.POST.get("reset_token")
    new_pwd = request.POST.get("new_password")
    if not all([reset_token, new_pwd]):
        return JsonResponse({"code":400, "msg":"参数不全"})
    # 校验token
    try:
        data = signing.loads(reset_token, salt="reset_pwd_salt", max_age=900)
        mobile = data.get("mobile")
    except signing.BadSignature:
        return JsonResponse({"code":400, "msg":"重置凭证无效或已过期"})
    # 获取用户
    try:
        profile = UserProfile.objects.get(mobile=mobile)
    except UserProfile.DoesNotExist:
        return JsonResponse({"code":400, "msg":"用户不存在"})
    # 修改密码
    profile.user.set_password(new_pwd)
    profile.user.save()
    # 清空验证码缓存
    cache.delete(f"reset_code_{mobile}")
    return JsonResponse({"code":200, "msg":"密码重置成功,请重新登录"})

注意事项

  • 要给短信接口加请求频率限制,避免被恶意刷短信
  • 新密码要做强度校验,比如长度不低于8位,包含字母数字等
  • salt值要保存在配置文件里,不要硬编码在业务代码中
  • 密码修改完成后,可选清理该用户的所有登录session,强制所有设备重新登录

内容的提问来源于stack exchange,提问作者Yabesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:18:05