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

Django中基于邮箱的双因素认证实现方案咨询

邮箱验证码双因素认证实现方案(无第三方2FA库)

一、验证码生成:基于签名令牌的无存储思路

不用单独生成随机码再存库,直接生成包含验证信息的签名令牌,把令牌作为核心验证载体发送给用户邮箱:

  • 核心逻辑:用HMAC算法(比如HMAC-SHA256)对用户ID、过期时间、随机短验证码(6位数字即可)进行签名,将这些信息拼接成一个不可篡改的令牌。
  • 具体步骤:
    1. 生成6位随机数字验证码(比如用random.randint(100000, 999999)生成)
    2. 计算过期时间戳(比如当前时间戳 + 300秒,即5分钟有效期)
    3. 拼接原始内容字符串:{user_id}:{code}:{expire_timestamp}
    4. 用服务器端专属密钥对原始字符串做HMAC签名,得到签名值
    5. 组合成最终令牌:{user_id}:{code}:{expire_timestamp}:{signature}
  • 优势:令牌本身包含所有验证所需信息,无需存数据库,过期时间直接内嵌在令牌里

二、验证码存储:两种轻量替代方案

1. 零存储方案

直接把生成的完整令牌(或者只发6位验证码,令牌存在服务器验证逻辑里)发送给用户邮箱,服务器端不保存任何验证码相关数据,完全依赖令牌的签名验证确保有效性。

2. Redis缓存存储(简化过期管理)

如果觉得纯令牌太长,可采用短链映射:

  • 生成短随机字符串作为key,把令牌存入Redis,并设置和令牌过期时间一致的TTL(自动过期)
  • 给用户发送带该key的链接(比如你的域名/verify?key=xxxx),用户提交后服务器从Redis取出令牌验证
  • 优势:Redis自动处理过期和清理,不用自己写过期逻辑,比数据库操作更高效

三、验证码验证流程

方案1:纯令牌验证(零存储)

用户输入收到的6位验证码后,服务器执行以下操作:

  1. 从当前登录上下文获取用户ID,拼接出{user_id}:{input_code}:{expire_timestamp}(这里的过期时间戳可以取当前时间往前推5分钟内的范围,或者让用户提交完整令牌直接解析)
  2. 用服务器密钥重新计算HMAC签名,对比和令牌中的签名是否一致
  3. 检查当前时间是否小于过期时间戳
  4. 所有条件满足则完成双因素认证

方案2:Redis缓存验证

用户通过短链接或提交key后:

  1. 根据key从Redis中取出对应的令牌
  2. 验证令牌的签名有效性和过期时间
  3. 对比用户输入的验证码和令牌中的验证码是否匹配
  4. 验证通过后立即删除Redis中的key,避免重复使用

四、额外优化细节

  • 请求频率限制:用Redis记录用户ID的验证码请求次数,比如1分钟内最多允许发送2次,防止恶意刷邮件
  • 防重复验证:不管是令牌过期还是Redis key被删除,都能确保验证码只能使用一次
  • 密钥安全:服务器端的HMAC密钥要妥善保管,避免泄露,防止令牌被伪造

内容的提问来源于stack exchange,提问作者Тв0р0бушек

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:00:05