SpringBoot项目实战:5分钟搞定阿里云短信验证码(附防刷Redis配置)
2026/6/9 1:34:36 网站建设 项目流程

SpringBoot实战:阿里云短信验证码集成与Redis防刷策略

短信验证码作为现代应用的身份验证基石,其稳定性和安全性直接影响用户体验和系统可靠性。对于Java开发者而言,如何在SpringBoot项目中快速集成阿里云短信服务,同时规避恶意刷取风险,是每个上线项目必须跨越的技术门槛。

1. 阿里云短信服务基础配置

在开始编码前,我们需要完成阿里云侧的准备工作。登录阿里云控制台,进入「短信服务」模块,这里需要重点关注三个核心配置项:

  1. 签名申请:选择签名类型为「验证码」,填写签名来源(如企业官网或APP名称),上传对应的资质证明文件
  2. 模板创建:新建「验证码」类型模板,内容示例:您的验证码为${code},5分钟内有效
  3. 权限配置:为操作账号开通AliyunDysmsFullAccess权限策略

注意:正式环境签名审核通常需要1-2个工作日,建议在项目初期就提前准备

关键参数获取位置:

参数类型获取路径示例
AccessKey控制台 > 访问控制 > 用户管理LTAI5txxxxxxxxxx
签名名称短信服务 > 签名管理阿里云验证
模板CODE短信服务 > 模板管理SMS_154950909

2. SpringBoot工程初始化

创建标准的SpringBoot项目后,首先配置必要的依赖项。除了基础的web starter,还需要添加:

<!-- 阿里云SDK核心库 --> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.16</version> </dependency> <!-- 短信服务专用SDK --> <dependency> <groupId>com.aliyun</groupId> <artifactId>dysmsapi20170525</artifactId> <version>2.0.23</version> </dependency> <!-- Redis集成 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>

application.yml中配置关键参数:

aliyun: sms: access-key-id: ${ALIYUN_ACCESS_KEY} access-key-secret: ${ALIYUN_ACCESS_SECRET} sign-name: 阿里云验证 template-code: SMS_154950909 endpoint: dysmsapi.aliyuncs.com spring: redis: host: localhost port: 6379 timeout: 3000

3. 验证码服务层实现

验证码生成建议采用线程安全的ThreadLocalRandom替代传统Random类:

public class VerificationCodeUtil { private static final String NUMBERS = "0123456789"; public static String generate(int length) { StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { int index = ThreadLocalRandom.current().nextInt(NUMBERS.length()); sb.append(NUMBERS.charAt(index)); } return sb.toString(); } }

短信发送服务实现要点:

@Service @RequiredArgsConstructor public class SmsService { private final AliyunSmsConfig smsConfig; public SendSmsResponse sendVerificationCode(String phone, String code) throws Exception { Config config = new Config() .setAccessKeyId(smsConfig.getAccessKeyId()) .setAccessKeySecret(smsConfig.getAccessKeySecret()); config.endpoint = smsConfig.getEndpoint(); Client client = new Client(config); SendSmsRequest request = new SendSmsRequest() .setPhoneNumbers(phone) .setSignName(smsConfig.getSignName()) .setTemplateCode(smsConfig.getTemplateCode()) .setTemplateParam("{\"code\":\"" + code + "\"}"); return client.sendSms(request); } }

4. Redis防刷策略深度优化

基础防刷方案存在三个潜在漏洞:

  1. 未限制单位时间发送次数
  2. 未校验验证码有效性
  3. 缺乏IP维度限制

改进后的Redis存储结构设计:

// 验证码存储Key设计 String codeKey = "sms:code:" + phone; // 发送次数计数Key设计 String countKey = "sms:count:" + phone; // IP限制Key设计 String ipKey = "sms:ip:" + ipAddress; // 复合校验逻辑 public boolean allowSend(String phone, String ip) { // 单IP每日限制 Long ipCount = redisTemplate.opsForValue().increment(ipKey); if (ipCount == 1) { redisTemplate.expire(ipKey, 1, TimeUnit.DAYS); } if (ipCount > 50) { return false; } // 手机号频次控制 Long phoneCount = redisTemplate.opsForValue().increment(countKey); if (phoneCount == 1) { redisTemplate.expire(countKey, 1, TimeUnit.HOURS); } return phoneCount <= 5; }

验证码校验服务示例:

public boolean verifyCode(String phone, String inputCode) { String storedCode = redisTemplate.opsForValue().get("sms:code:" + phone); if (storedCode == null || !storedCode.equals(inputCode)) { return false; } // 验证通过后立即删除缓存 redisTemplate.delete("sms:code:" + phone); return true; }

5. 生产环境注意事项

性能优化

  • 使用连接池配置RedisTemplate
  • 对短信发送接口实现异步处理
  • 添加熔断机制(如Sentinel)防止短信服务不可用

安全增强

// 图形验证码前置校验 @GetMapping("/sms/code") public Result requestSmsCode( @RequestParam String phone, @RequestParam String captcha, HttpServletRequest request) { String sessionCaptcha = (String) request.getSession() .getAttribute("captcha"); if (!captcha.equalsIgnoreCase(sessionCaptcha)) { return Result.fail("图形验证码错误"); } // ...后续短信发送逻辑 }

监控建议

  1. 通过阿里云云监控设置短信发送量告警
  2. 记录Redis防刷触发日志用于安全审计
  3. 定期统计各手机号验证码使用情况

在用户注册流程中,建议采用以下验证链:

  1. 前端图形验证码
  2. 短信验证码频率控制
  3. 最终验证码校验
  4. 注册成功后的风控检查

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询