【Springboot实战】如何发送短信验证

阿里云注册短信服务似乎会送一些免费的额度,这波又被我白嫖到了😁😁😁

90条短信,做测试足够了

一、需求分析

  1. 场景:用户输入自己的手机号,点击获取验证码
  2. 分析:防止刷爆:可以限制一分钟获取一次,
    • 前端:时效内禁用button
    • 后端:存入redis设置过期时间,请求先判断redis中是否有数据。

二、短信服务和配置

第三方短信服务运营商

  • 阿里云
  • 腾讯云
  • 华为云

这里我白嫖阿里的

1、短信服务

进入阿里云官网并登录,顶部搜索短信服务

登录

2、进入短信服务控制台

3、添加签名

选择国内消息菜单,首先添加短信签名,用于标识短信发送者的身份

4、添加模板

其次申请短信模板,用于定义发送短信的内容格式。

短信模板的内容就自己定义,规则自己多看看,这里我就不说了,我也两次没通过😵‍💫😵‍💫

签名和模板需要等待大概一个多小时的时间

这里我添加了两个模板

 SMS_460610080
 SMS_460600077

5、AccessKey管理

鼠标移动到右上角用户头像上,在弹出的窗口中点击[AccessKey管理],类似于用户名密码,提供于程序中访问阿里云鉴权

6、选择子用户

进入后,可以选择使用子用户,权限更小,不小心泄露AccessKey导致的危害比较小,但操作相对繁琐

7、创建账户

首先需要创建一个用户,可以其中控制只允许OpenAPI调用访问

8、获取AccessKey

创建好后会生成一对AccessKey,需要妥善保管,防止泄露

用户登录名称 xxxxxxxxxx.onaliyun.com
 AccessKey ID xxxxxxxxxxxxxxxxxxx
 AccessKey Secret xxxxxxxxxxxxxxx

9、授予权限

点击创建好的用户,给其授予相应的短信服务权限

10、测试短信发送

可利用官方提供的openAPI

SendSms短信服务API调试-阿里云OpenAPI开发者门户 (aliyun.com)

三、后端开发

1、环境搭建

1)导入坐标

 <!--短信验证码所需jar包-->
         <dependency>
             <groupId>com.aliyun</groupId>
             <artifactId>aliyun-java-sdk-core</artifactId>
             <version>4.5.16</version>
         </dependency>
         <dependency>
             <groupId>com.aliyun</groupId>
             <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
             <version>2.1.0</version>
         </dependency>

 2)由于我们需要使用redis缓存验证码因此还要

导入redis的jar包
 <!--     使用redis缓存验证码时效-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-data-redis</artifactId>
          </dependency>

3)在yml文件中配置redis,设置了redis密码记得加上密码配置

spring:
   redis:
     host: xxxxx
     port: 6379
     password: sssss
     lettuce:
       pool:
         max-active: 8 # 最大连接
         max-idle: 8 # 最大空闲连接
         min-idle: 0 # 最小空闲连接
         max-wait: 100ms # 最大等待时长

2、代码开发

复制官方提供的测试案例,填充在服务配置中获取的相应的参数即可

代码模板:SendSms短信服务API调试-阿里云OpenAPI开发者门户 (aliyun.com)

1️⃣工具类
 
public class SMSUtils {
 ​
     // 阿里云账号AccessKey信息
     相当于用户和密码
     private static final String ACCESS_KEY_ID = "xxxxxxxxxx";
     private static final String ACCESS_KEY_SECRET = "xxxxxxxxxxxxx";
 ​
     /**
      * 发送短信
      *
      **/
         // 短信API产品域名(接口地址固定,无需修改)
         final String DOMAIN = "dysmsapi.aliyuncs.com";
         // 设置区域
         final String REGION_ID = "cn-hangzhou";
 ​
         // 初始化acsClient,暂不支持region化
         DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
         IAcsClient client = new DefaultAcsClient(profile);
 ​
         // 组装请求对象-具体描述见控制台-文档部分内容
         SendSmsRequest request = new SendSmsRequest();
         // 必填:待发送手机号
         request.setPhoneNumbers(phoneNumbers);
         // 必填:短信签名-可在短信控制台中找到
         request.setSignName("星球守护者");
         // 必填:短信模板-可在短信控制台中找到
         request.setTemplateCode("SMS_460610080");
         // 选填:设置模板参数,多个参数用逗号隔开
         request.setTemplateParam("{\"code\":\"" + 123456 + "\"}");
 ​
         try {
             // 获取发送结果
             SendSmsResponse response = client.getAcsResponse(request);
             System.out.println(response);
         } catch (ServerException e) {
             e.printStackTrace();
         } catch (ClientException e) {
             // 打印处理结果
             System.out.println("ErrCode:" + e.getErrCode());
             System.out.println("ErrMsg:" + e.getErrMsg());
             System.out.println("RequestId:" + e.getRequestId());
         }
     }
 }

短信模板Code——TemplateCode

点击详情就可以看到模板code,将其复制

2️⃣编写短信服务接口
 @RestController
 @CrossOrigin("http://localhost:63342")
 public class SendCode {
     /**
      * @param targetPhone 用户手机号
      * @return
      */
     @GetMapping("/getCode01")
     @ResponseBody
     public String phone01(@RequestParam("targetPhone") String targetPhone) {
         //生成六位数验证码
         int authNum = new Random().nextInt(899999) + 100000;
         String authCode = String.valueOf(authNum);
         SMSUtils.sendMessage(targetPhone,authCode);
         return "发送成功";
     }
 }
3️⃣启动服务测试接口
 GET http://localhost:8080/getCode01?targetPhone=18279025559

效果:

APifox显示的是发送成功

手机:

至此我们已经成功实现了调用阿里云短信服务发送验证码的功能

四、缓存改进

如果仅仅是上述那样,当碰到恶意用户时,不断地给点击请求,那对系统会造成损害,因此可以引入缓存来简单改进代码

这里需要加上redis缓存

所以需要增加一个redis客户端的配置类

1、增加redis配置

@Configuration
 public class RedisConfig {
     @Bean
     public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
         //创建RedisTemplate对象
         RedisTemplate<String,Object> template=new RedisTemplate<>();
         //设置来凝结工厂
         template.setConnectionFactory(connectionFactory);
         //创建JSON序列化
         GenericJackson2JsonRedisSerializer jsonRedisSerializer=new GenericJackson2JsonRedisSerializer();
         //设置key的序列化
         template.setKeySerializer(RedisSerializer.string());
         template.setHashKeySerializer(RedisSerializer.string());
         //设置Value的序列化
         template.setValueSerializer(jsonRedisSerializer);
         template.setHashValueSerializer(jsonRedisSerializer);
         //返回
         return template;
     }
 }

2、SMS工具类

public class SMSUtils {
 ​
     // 阿里云账号AccessKey信息
     private static final String ACCESS_KEY_ID = "ddddddddddddddd";
     private static final String ACCESS_KEY_SECRET = "cdddddddddddddd";
 ​
     /**
      * 发送短信
      *
      * @param phoneNumbers 收信人手机号
      * @param param        发送的验证码
      */
     public static void sendMessage(String phoneNumbers, String param) {
         // 短信API产品名称(短信产品名固定,无需修改)
         final String PRODUCT = "Dysmsapi";
         // 短信API产品域名(接口地址固定,无需修改)
         final String DOMAIN = "dysmsapi.aliyuncs.com";
         // 设置区域
         final String REGION_ID = "cn-hangzhou";
 ​
         // 初始化acsClient,暂不支持region化
         DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
         IAcsClient client = new DefaultAcsClient(profile);
 ​
         // 组装请求对象-具体描述见控制台-文档部分内容
         SendSmsRequest request = new SendSmsRequest();
         // 必填:待发送手机号
         request.setPhoneNumbers(phoneNumbers);
         // 必填:短信签名-可在短信控制台中找到
         request.setSignName("星球守护者");
         // 必填:短信模板-可在短信控制台中找到
         request.setTemplateCode("SMS_460600077");
         // 选填:设置模板参数,多个参数用逗号隔开
         //param:随机生成的验证码
         request.setTemplateParam("{\"code\":\"" + param + "\"}");
 ​
         try {
             // 获取发送结果
             SendSmsResponse response = client.getAcsResponse(request);
             System.out.println(response);
             System.out.println("短信发送成功!");
         } catch (ServerException e) {
             e.printStackTrace();
         } catch (ClientException e) {
             // 打印处理结果
             System.out.println("ErrCode:" + e.getErrCode());
             System.out.println("ErrMsg:" + e.getErrMsg());
             System.out.println("RequestId:" + e.getRequestId());
         }
     }
 }
 ​


 

3、controller层代码

 @Autowired
     private RedisTemplate<String,Object> redisTemplate;
     @GetMapping("/getCode02")
     @ResponseBody
     public String phone02(@RequestParam("targetPhone") String targetPhone) {
         // 发送前先看下我们是否已经缓存了验证码
         String yzm = (String) redisTemplate.opsForValue().get("yzm");
         // 判断是否存在
         if (yzm == null){
             // 生成六位数验证码
             int authNum = new Random().nextInt(899999) + 100000;
             String authCode = String.valueOf(authNum);
             // 不存在,我们发送验证码给用户
             SMSUtils.sendMessage(targetPhone,authCode);
             // 存入redis中,设置有效期为1分钟
             redisTemplate.opsForValue().set("yzm", authCode, 1, TimeUnit.MINUTES);
             return "发送成功";
         }
         // 存在,直接返回,不再发送验证码~
         return "请勿重复发送验证码";
     }
 

访问地址:

 http://localhost:8080/getCode02?targetPhone=xxxxxxx

重新多次测试接口查看效果,可发现短时间内只能获取一次:

六、发送短信

前面我们演示了发送短信验证码,但是如果我们不发验证码,只要短信那该咋办

不揍呢,其实和前面的差不多

1、创建新的签名

2、创建新的模板

这里不得不吐槽一下

我等个签名验证,等了四个小时,等的我人都睡着了,这摸鱼🐟也忒猛了点

其他小伙伴要是搞这个,还是边看斗罗大陆吧😂😂😂

3、修改代码

上面的代码只需要修改一下SMSUtils工具类即可

测试的话,用getcode01就行

结果:

测试成功,手机收到短信。如果你们没收到,可别怪我啊!!!

到这里你一定会想,那我不是可以随便给人发骚扰短信了😼😼😼,可以随所欲为了。

确实是可以的,不过好像是不能连续发送的,原因不知,经验所得

只有经过测试的手机号才可以正常发送短信

 我的分享到此结束,如果感兴趣的小伙伴,请点赞、评论、关注一下吧!谢谢!

  • 17
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值