阿里云注册短信服务似乎会送一些免费的额度,这波又被我白嫖到了😁😁😁
90条短信,做测试足够了
一、需求分析
- 场景:用户输入自己的手机号,点击获取验证码
- 分析:防止刷爆:可以限制一分钟获取一次,
- 前端:时效内禁用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就行
结果:
测试成功,手机收到短信。如果你们没收到,可别怪我啊!!!
到这里你一定会想,那我不是可以随便给人发骚扰短信了😼😼😼,可以随所欲为了。
确实是可以的,不过好像是不能连续发送的,原因不知,经验所得
只有经过测试的手机号才可以正常发送短信
我的分享到此结束,如果感兴趣的小伙伴,请点赞、评论、关注一下吧!谢谢!