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

申请短信服务 我使用的是阿里云的短信服务,然后就可以获得这两个值:
Redis|Redis缓存手机验证码实战(包含SpringBoot的灵魂)
文章图片

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

com.aliyun dysmsapi20170525 2.0.1

将客户端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

【Redis|Redis缓存手机验证码实战(包含SpringBoot的灵魂)】注: (想让属性配置文件有自定义属性配置类的提示就得引用依赖)
org.springframework.boot spring-boot-configuration-processor true

实战使用
/** * @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; }}

    推荐阅读