一、开通阿里云短信服务

  1. 添加模板:

即发送到手机上短信的具体信息,比如:您的验证码${code},该验证码5分钟内有效,请勿泄漏于他人!

  1. 添加签名

注:命名尽量有实际意义。

二、分析流程

(1)重点:验证码(实际上是后端生成的4位验证码),手机号(需要传入指定手机号,不然阿里云不知道要发给谁),验证码会定时过期,防止多次请求。
(2)首先后端生成随机验证码,与手机号一起传到阿里云上,阿里云向该手机号发送该验证码,发送成功之后将该验证码存入redis中,以(手机号,验证码)的形式存入,并设置有效时长。(这样就结束了吗?)
(3)为了防止恶意的验证码请求,应该将其加入redis中,并利用其可以设置过期时间的特点进行定时。在验证码请求之前,先去redis中查看是否存在该key,若存在,则不进行验证码请求,若不存在,再进行验证码获取。

三、 具体实现:

  1. 导入依赖
<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
        </dependency>
    </dependencies>
  1. 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("短信发送失败");
        }
  1. 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(验证码)值?

  1. 在阿里云的文档中,这么介绍,短信模板的得是Json格式。
  2. 手机验证码存储到redis中 短信验证码存放在哪里_ci

  3. 使用HashMap(key-value)方便对其进行转化,之前引入了fastjson此时就可以使用到。
//在service层中对request的设置,param是当时传入的验证码(HashMap)。
	JSONObject.toJSONString(param);