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

基于API与PHP的短信OTP验证:如何安全校验验证码?

OTP验证方案建议

核心思路:避免存储手机号,用临时令牌关联OTP

不用直接存手机号,而是在发送OTP前生成一个唯一临时令牌,把令牌和OTP绑定存储,同时将令牌通过安全方式发给前端。验证时前端提交令牌+输入的OTP,后端匹配校验即可。

具体实现方案

方案1:数据库临时表存储(适合无缓存服务的场景)

  • 创建独立的otp_verifications表,不需要手机号字段,只需包含:
    • token_hash: 唯一随机字符串(比如32位UUID)的哈希值(用SHA-256加密,避免明文泄露)
    • otp_hash: 6位OTP的哈希值(用bcrypt加盐存储,防止暴力破解)
    • expires_at: 过期时间(比如设为5分钟后,避免OTP长期有效)
    • is_used: 布尔值,标记是否已使用,防止重复验证
  • 流程:
    1. 用户提交手机号,后端生成6位OTP和32位UUID令牌
    2. 将令牌哈希、OTP哈希、过期时间存入表中
    3. 把原始令牌存入HttpOnly、Secure属性的Cookie(前端无法读取,避免泄露风险)
    4. 调用短信API给用户发送OTP
    5. 用户输入OTP提交后,后端从Cookie中获取令牌,哈希后去表中查找对应记录
    6. 校验OTP哈希是否匹配、是否过期、是否未使用,通过则标记记录为已使用,验证成功

方案2:Redis缓存存储(更适合临时数据,性能更高)

  • 用Redis键值对存储,不用建表:
    • 键:格式为otp:token:{UUID},其中UUID是生成的唯一令牌
    • 值:JSON格式,包含otp_hash和expire_at
    • 直接给Redis键设置过期时间(比如5分钟),到期自动清理,无需手动维护
  • 流程和方案1一致,只是把存储介质换成Redis,验证时直接根据令牌键查找值,校验逻辑相同

关于触发器/存储过程的说明

触发器和存储过程在这里完全没必要用,它们主要用于数据库层面的自动化操作(比如数据变更时触发动作),而OTP验证是业务逻辑层面的处理,用普通业务代码实现更灵活、易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:00:59