Redis缓存手机验证码实战(包含SpringBoot的灵魂)

申请短信服务

我使用的是阿里云的短信服务,然后就可以获得这两个值:
在这里插入图片描述

引入依赖

这个依赖包含一个短信服务客户端Client:

  
  <dependency>
      <groupId>com.aliyungroupId>
      <artifactId>dysmsapi20170525artifactId>
      <version>2.0.1version>
  dependency>

将客户端Client整合到SpringBoot中【灵魂】

方式一:原生SpringBoot配置过程(推荐方式二)

客户端自动配置类

/**
 * @Author: xiang
 * @Date: 2021/4/29 16:58
 *
 * 短信访问客户端
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SmsProperties.class) //指对应的明属性配置类
@AutoConfigureAfter(RedisAutoConfiguration.class) //短信功能依赖redis
public class SmsAutoConfiguration {

    //短信客户端属性配置类
    private final SmsProperties properties;

    //从容器中拿到属性配置类
    public SmsAutoConfiguration(SmsProperties properties) {
        this.properties = properties;
    }

    /**
     * 阿里云短信访问客户端对象注入IOC容器
     * @return
     * @throws Exception
     */
    @Bean
    public Client getSmsClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId(properties.getAccessKeyId())
                .setAccessKeySecret(properties.getAccessKeySecret());
        // 访问的域名
        config.endpoint = properties.getEndpoint();
        return new Client(config);
    }

}

自动配置类的属性类

/**
 * @Author: xiang
 * @Date: 2021/4/29 17:07
 *
 * 短信访问客户端属性配置类
 */
@ConfigurationProperties(prefix = "spring.redis.sms")
public class SmsProperties {
    private String accessKeyId;
    private String accessKeySecret;
    // 短信发送请求访问的域名
    private String endpoint = "dysmsapi.aliyuncs.com";

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }
}

方式二:简化方式 直接@Value注入属性值(推荐)

只是:这种方式注释的每一种属性都必须要在配置文件中配置

/**
 * @Author: xiang
 * @Date: 2021/5/11 20:31
 */
@Configuration
public class SmsConfig {

    @Value("${spring.redis.sms.access-key-id}")
    private String accessKeyId;

    @Value("${spring.redis.sms.access-key-secret}")
    private String accessKeySecret;

    // 短信发送请求访问的域名
    private String endpoint = "dysmsapi.aliyuncs.com";

    /**
     * 阿里云短信访问客户端对象注入IOC容器
     * @return
     * @throws Exception
     */
    @Bean
    public Client getSmsClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = endpoint;
        System.out.println("-----执行新的SmsConfig-----");
        return new Client(config);
    }

}

属性文件配置

以后直接属性配置文件中配置申请的AccessKeyId与AccessKeySecret就行

 阿里云短信通知配置
 spring:
 	redis:
		sms:
			access-key-id: xxxxxxxxxxxxxx #AccessKeyId
			access-key-secret: yyyyyyyyyyyyyyyyyyyyyyy #AccessKeySecret

注: (想让属性配置文件有自定义属性配置类的提示就得引用依赖)

  
  <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-configuration-processorartifactId>
      <optional>trueoptional>
  dependency>

实战使用

/**
 * @Author: xiang
 * @Date: 2021/4/28 13:35
 */
@RestController
public class PhoneCodeController {

	//redis操作模板
    private RedisTemplate redisTemplate;
    //短信发送客户端
    private Client smsClient;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setSmsClient(Client smsClient) {
        this.smsClient = smsClient;
    }

    //发送验证码
    @GetMapping("/phone")
    public String sendPhoneCode(@RequestParam("phone") String phone) throws Exception {
        //生成验证码
        int code = (int)((Math.random() * 9 + 1) * 100000);

        //同一个电话一天最多发送5次
        //保存验证次数
        String countKey = "verifyCode"+phone+":count";

        Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
        if (count == null){
            redisTemplate.opsForValue().set(countKey,1,1, TimeUnit.DAYS);
        } else if (count < 6){
            redisTemplate.opsForValue().increment(countKey);
        }else {
            return "今天验证次数已用完";
        }

        //阿里云短信服务发送短信
        String resultCode = sendCode(phone, code);

        if ("OK".equals(resultCode)){
            //保存验证码(两分钟有效时间)
            String codeKey = "verifyCode"+phone+":code";
            redisTemplate.opsForValue().set(codeKey,code,2,TimeUnit.MINUTES);
            return "发送成功";
        }
        return "发送失败";
    }

    //验证
    @GetMapping("/phoneCode")
    public Boolean verifyCode(@RequestParam("phone") String phone,@RequestParam("code") Integer code){
        String codeKey = "verifyCode"+phone+":code";
        Integer result = (Integer) redisTemplate.opsForValue().get(codeKey);
        if (result.equals(code)) return true;
        return false;//会直接返回错误页面
    }

    private String sendCode(String phone,int code) throws Exception {
        SendSmsRequest smsRequest = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName("[测试专用]阿里云通信")
                .setTemplateCode("[测试专用]阿里云通信测试模版")
                .setTemplateParam("{\"code\":"+code+"}"); //需要json样式
        //发送请求
        SendSmsResponse smsResponse = smsClient.sendSms(smsRequest);
        //返回请求状态码
        return smsResponse.body.code;
    }

}

你可能感兴趣的:(Redis,Spring,spring,boot,redis)