手机验证码功能开发:整合阿里云短信服务
手机号验证码发送与校验。
目前很多应用登录方式已经从传统账号密码登录,逐渐转向手机号验证码登录:
输入手机号
↓
获取验证码
↓
短信发送
↓
输入验证码
↓
完成登录
整个流程中,短信发送负责通知用户,而验证码校验负责确认用户身份。
一、为什么需要短信验证码?
在用户系统中,手机号通常代表用户身份。
例如:
- 用户注册
- 手机号登录
- 找回密码
- 修改手机号
- 安全验证
这些场景都需要确认:
当前操作的人是否真的拥有这个手机号。
短信验证码就是一种简单有效的身份验证方式。
二、短信发送服务介绍
在真实项目中,我们不会自己搭建短信网关,而是接入第三方短信服务。
常见服务商:
- 阿里云短信服务
- 腾讯云短信
- 华为云短信
本项目使用阿里云短信服务完成验证码发送。
短信发送流程:
用户请求验证码
↓
业务服务器生成验证码
↓
调用阿里云短信 API
↓
阿里云发送短信
↓
用户收到验证码
三、阿里云短信服务有什么作用?
阿里云短信服务主要负责:
1. 短信通道
我们的服务器不直接连接运营商。
而是:
业务系统
↓
阿里云短信服务
↓
运营商
↓
用户手机
阿里云负责短信发送链路。
2. 短信模板管理
短信内容通常不是随便发送的。
例如:
您的验证码为${code},
有效时间3分钟。
其中验证码部分是动态参数。
发送时:
code = 829301
阿里云会自动替换模板内容。
3. 接入认证
调用阿里云 API 时,需要提供:
- AccessKey ID
- AccessKey Secret
它们相当于调用接口的身份凭证。
项目中一般会放在配置文件中:
application.yml
aliyun:
accessKeyId:
accessKeySecret:
实际生产环境建议使用:
- 环境变量
- 配置中心
- 密钥管理服务
避免泄露。
四、验证码整体设计
一个完整验证码流程:
第一步:用户请求验证码
用户输入手机号:
138xxxx8888
服务器收到请求后:
生成随机验证码:
839201
第二步:保存验证码到 Redis
验证码属于临时数据,非常适合 Redis。
保存:
key:
verification_code:138xxxx8888
value:
839201
expire:
3分钟
为什么不用数据库?
因为验证码:
- 生命周期短
- 访问频繁
- 不需要永久保存
Redis 更适合这种场景。
第三步:调用阿里云发送短信
服务器调用阿里云短信接口:
业务服务
↓
阿里云 SDK
↓
短信平台
↓
用户手机
用户收到:
您的验证码为839201
请在3分钟内完成验证
第四步:用户提交验证码
用户输入:
839201
服务器查询 Redis:
用户输入验证码
↓
Redis保存验证码
比较是否一致。
第五步:验证成功
如果验证码正确:
验证码匹配成功
↓
删除Redis验证码
↓
继续业务流程
例如:
- 创建用户
- 登录系统
- 修改密码
五、为什么验证码需要 Redis?
1. 自动过期
验证码不应该永久有效。
例如:
验证码:
123456
有效时间:
3分钟
Redis 可以自动删除过期数据。
2. 提高性能
验证码属于高频访问:
大量用户请求
↓
Redis内存读取
↓
快速返回
避免频繁访问数据库。
3. 支持分布式项目
在微服务架构:
用户服务
订单服务
认证服务
多个服务都需要验证用户状态。
Redis 可以作为共享缓存。
六、验证码安全设计
一个简单验证码功能,还需要考虑安全问题。
1. 防止频繁发送
避免用户疯狂点击:
获取验证码
获取验证码
获取验证码
通常限制:
60秒只能发送一次
2. 限制验证码有效时间
例如:
3分钟后失效
防止验证码长期泄露。
3. 验证成功立即删除
避免:
验证码使用一次
再次重复使用
验证成功后:
删除 Redis 数据。
4. 限制错误次数
例如:
连续错误5次
暂时禁止验证
降低暴力破解风险。
七、项目中的技术组合
本次验证码功能涉及:
Spring Boot
+
RedisTemplate
+
Redis
+
阿里云短信 SDK
+
线程池异步发送
整体流程:
用户
↓
认证服务
↓
生成验证码
↓
保存 Redis
↓
调用阿里云短信
↓
用户收到验证码
↓
提交验证码
↓
Redis校验
八、总结
短信验证码虽然功能简单,但是一个完整系统需要考虑:
- 第三方短信服务接入
- 验证码生成
- Redis缓存管理
- 过期控制
- 防刷策略
- 安全验证
通过:
阿里云短信服务 + Redis + Spring Boot
我们就完成了一套真实项目中的验证码体系。
后续可以继续实现:
- 用户注册接口
- 手机号登录
- Sa-Token 登录认证
- RBAC 权限控制
逐步完善完整用户中心模块。