一、开通阿里云短信服务
- 添加模板:
即发送到手机上短信的具体信息,比如:您的验证码${code},该验证码5分钟内有效,请勿泄漏于他人!
- 添加签名
注:命名尽量有实际意义。
二、分析流程
(1)重点:验证码(实际上是后端生成的4位验证码),手机号(需要传入指定手机号,不然阿里云不知道要发给谁),验证码会定时过期,防止多次请求。
(2)首先后端生成随机验证码,与手机号一起传到阿里云上,阿里云向该手机号发送该验证码,发送成功之后将该验证码存入redis中,以(手机号,验证码)的形式存入,并设置有效时长。(这样就结束了吗?)
(3)为了防止恶意的验证码请求,应该将其加入redis中,并利用其可以设置过期时间的特点进行定时。在验证码请求之前,先去redis中查看是否存在该key,若存在,则不进行验证码请求,若不存在,再进行验证码获取。
三、 具体实现:
- 导入依赖
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
</dependencies>
- Contorller层:
(1)引入redisTemplate,方便后续查询redis操作。
@Autowired
private RedisTemplate<String,String> redisTemplate;
(2)使用验证码发送之前,查询redis是已经存在了该手机号的验证码。
//phone为手机号,判断rdis中对应手机号的验证码是否为空。
String code = redisTemplate.opsForValue().get(phone);
if(!StringUtils.isEmpty(code)){
return R.ok();
}
(3)若不存在,使用工具类生成随机验证码,存入到HashMap中。最后使用send方法,将验证码与手机号一起发送到阿里云,成功则返回true,否则false。
//生成随机值,传递阿里云进行发送
code= RandomUtil.getFourBitRandom();
//以key-value的形式存储,方便后面转化
Map<String,Object> param=new HashMap<>();
param.put("code",code);
//send方法将在service层具体介绍。
boolean isSend=msmService.send(param,phone);
(4)最后,判断返回值是否为true,如为true,则将手机号,验证码以key-value的形式存入redis,并设置有效时长。否则,返回错误信息。
if(isSend){
//发送成功,则把验证码放到redis里,redisTemplate.opsForValue().set()
//设置有效时间
//参数(手机号,验证码,数字,时间单位),如下,为5分钟。
redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
return R.ok();
}else{
return R.error().message("短信发送失败");
}
- Service层
主要对传入的手机号和验证码进行处理,发至阿里云,阿里云再返回结果,并发送短信至对应手机上。
//获取阿里云的keyid以及secret
String KeyID= ConstantPropertiesUtils.ACCESS_KEY_ID;
String KeySecret=ConstantPropertiesUtils.ACCESS_KEY_SECRET;
//传入
DefaultProfile profile=DefaultProfile.getProfile("default",KeyID,KeySecret);
//创建一个IAcsClient客户端
IAcsClient client = new DefaultAcsClient(profile);
//设置相关固定参数(无需改变)
CommonRequest request = new CommonRequest();
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
//前面的name固定,后面设置对应的签名及模板码
request.putQueryParameter("PhoneNumbers", phone);//手机号
request.putQueryParameter("SignName", "签名名称");//签名名称
request.putQueryParameter("TemplateCode","模板码");//模板code
request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));
try {
//将设置好一系列参数的request传入
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
//通过response获取是否成功
boolean success = response.getHttpResponse().isSuccess();
return success;
} catch (Exception e) {
e.printStackTrace();
return false;
}
补充:
为什么建议使用HashMap存储code(验证码)值?
- 在阿里云的文档中,这么介绍,短信模板的得是Json格式。
- 使用HashMap(key-value)方便对其进行转化,之前引入了fastjson此时就可以使用到。
//在service层中对request的设置,param是当时传入的验证码(HashMap)。
JSONObject.toJSONString(param);