如何实现短信验证码存储_mysql验证码表设计

5次阅读

短信验证码表应设计为:id 主键、phone 标准化手机号、code 加密存储、send_at 精确时间、used 标记使用状态、ip 和 scene 可选;建 (phone,used,send_at) 联合索引和 (send_at) 单索引;生产环境存哈希值;有效期 5 分钟动态计算;每日清理已用超 24 小时记录。

如何实现短信验证码存储_mysql 验证码表设计

短信验证码通常需要短期存储、高频读写、自动过期,MySQL 表设计要兼顾安全性、查询效率和清理便利性。核心原则是:字段精简、索引合理、过期机制明确、避免明文存验证码(尤其生产环境)。

基础表结构设计(含关键字段)

以下是一个推荐的 sms_verify_code 表结构:

  • id:BIGINT UNSIGNED AUTO_INCREMENT,主键,便于分页或日志追踪(非必须但建议)
  • phone:VARCHAR(16),标准化手机号(如 +8613912345678 或 13912345678),不加索引前需统一格式
  • code:CHAR(6) 或 VARCHAR(10),存实际验证码(测试 / 开发可明文;生产建议加密存储或仅存哈希)
  • send_at:DATETIME(3) 或 TIMESTAMP(3),精确到毫秒,记录发送时间(用于计算有效期)
  • used:TINYINT(1) DEFAULT 0,标记是否已被验证使用(防止重放)
  • ip:VARCHAR(45),可选,记录请求 IP,辅助风控
  • scene:VARCHAR(20),可选,标识用途(如 “login”, “register”, “reset_pwd”),方便多业务复用

必须添加的索引策略

没有合适索引,查验证码会变慢甚至拖垮数据库:

  • 联合索引 (phone, used, send_at):覆盖最常用查询 ——“查该手机号未使用且未过期的最新码”
  • 单独索引 (send_at):支撑定时任务快速找出所有过期记录(例如:WHERE send_at
  • 避免对 code 建索引 —— 无业务意义,还增加写开销

安全与生产注意事项

直接存明文验证码在 MySQL 中存在风险,尤其当数据库被脱库时:

  • 开发 / 测试环境可暂存明文,但上线前必须改
  • 生产环境建议:存储 code 的 SHA-256 哈希值(如 SHA2(CONCAT(code, salt, phone), 256)),验证时对用户输入做同样哈希比对
  • 限制单手机号单位时间内的发送频次(应用层 + 缓存层控制,如 Redis 计数),MySQL 表不承担限流职责
  • 验证码有效期统一设为 5 分钟,数据库不存 expire_at 字段,用 send_at + INTERVAL 5 MINUTE 动态计算,省空间且不易出错

配套清理机制(别只建表不清理)

验证码表会持续增长,必须定期归档或清理:

  • 每日凌晨执行:DELETE FROM sms_verify_code WHERE send_at
  • 保留已使用记录 24 小时,便于审计;未使用超时记录可更早清理(如 30 分钟后)
  • 大表场景下,考虑按月分区(如按 send_at RANGE 分区),提升删除效率
星耀云
版权声明:本站原创文章,由 星耀云 2026-01-07发表,共计1195字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。