一:认证服务环境搭建

1.新建gulimail-auth-server

java 短信验证码脱敏 java 短信验证码防刷_redis

2.整合相关依赖

java 短信验证码脱敏 java 短信验证码防刷_redis_02

<!--引入commom依赖-->
        <dependency>
            <groupId>com.sysg.gulimail</groupId>
            <artifactId>gulimail-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!--排除掉数据库相关依赖-->
            <exclusions>
                <exclusion>
                    <groupId>com.baomidou</groupId>
                    <artifactId>mybatis-plus-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

3.将gulimail-auth-server配置进nacos

1)在application.properties配置文件中配置

spring.application.name=gulimail-auth-server
spring.cloud.nacos.discovery.server-sddr=127.0.0.1:8848
server.port=20000

2)在主启动类添加注解

//开启服务注册发现功能
@EnableDiscoveryClient

//开启服务远程调用功能
@EnableFeignClients

3)开启服务

java 短信验证码脱敏 java 短信验证码防刷_java 短信验证码脱敏_03

4.导入登录注册页面

将静态资源放到nginx里面,实现动静分离

5.配置网关

- id: gulimail_auth_route
          uri: lb://gulimail-auth-server
          predicates:
            - Host=auth.gulimail.com

二:springMVC映射请求到页面

1.新建config

@Configuration
/**
 * 页面跳转控制类
 */
public class GulimailWebConfig implements WebMvcConfigurer {
    /**
     * 视图映射
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login.html").setViewName("login");
        registry.addViewController("/reg.html").setViewName("reg");
    }
}

三:验证码倒计时

1.点击验证码,进入60秒倒计时

<a id="sendCode">发送验证码</a>
$(function () {
		$("#sendCode").click(function () {
			/**
			 * 1.给指定手机发送验证码
			 * 2.添加验证码倒计时功能
			 */
			//判断有没有正在进行倒计时操作
			if($(this).hasClass("disabled")){
				//正在倒计时
			} else {
			//给指定的手机发送验证码
				let phone = $("#phoneNumber").val();
				$.get("/sms/controller?phone="+phone);
				timeoutChangeStyle();
			}
		});
	});
	let num = 60;
	function timeoutChangeStyle(){
		$("#sendCode").attr("class","disabled");
		if( num == 0){
			$("#sendCode").text("发送验证码");
			num = 60;
			$("#sendCode").attr("class","");
		} else {
			let str = num+"s 后再次发送";
			$("#sendCode").text(str);
			setTimeout("timeoutChangeStyle()",1000);
		}
		num--;
	}

四:阿里云配置发送短信验证码

1.登陆阿里云,购买0元五次套餐

java 短信验证码脱敏 java 短信验证码防刷_java 短信验证码脱敏_04

2.短信验证码接口

调用地址:http(s)://dfsns.market.alicloudapi.com/data/send_sms

请求方式:POST

返回类型:JSON

java 短信验证码脱敏 java 短信验证码防刷_验证码_05

3.代码实现

package com.sysg.gulimail.thirdparty.component;

import com.sysg.gulimail.thirdparty.util.HttpUtils;
import lombok.Data;
import org.apache.http.HttpResponse;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
@Data
@Component
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
public class SmsCpmponent {
    private String host;
    private String path;
    private String templateId;
    private String appcode;

    public void sendSmsCode(String phone,String code){
        String method = "POST";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("content", "code:"+code);
        bodys.put("phone_number", phone);
        bodys.put("template_id", templateId);
        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • host;path;templateId;appcode等参数动态配置
  • @ConfigurationProperties(prefix = “spring.alicloud”)将配置信息绑定到配置文件
#数据源
spring:
  cloud:
    #nacos地址
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    #阿里云的子系统用户名和密码
    alicloud:
      access-key: LTAIfwfwfwewefewfoZ5dh
      secret-key: disClqm4wefwefewff
      oss:
        endpoint: osfwefwef.com
        bucket: gulimail-sysg
      sms:
        host: https://dfsns.market.alicloudapi.com
        path: /data/send_sms
        templateId: TPL_0000
        appcode: 712wefwefweab39a78

  #服务的名称,用于让nacos知道那个服务正在被调用
  application:
    name: gulimail-third-party
#端口
server:
  port: 30000

4.本地调试

1)引入httpUtil依赖

https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java

2)引入processor依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

3)测试成功

五:短信验证码后台接口

1.新建SmsSendController,用来处理短信验证码发送功能

@RestController
@RequestMapping("/sms")
public class SmsSendController {
    @Autowired
    private SmsComponent smsComponent;
    /**
     * 提供给别的服务进行调用
     * @param phone
     * @param code
     * @return
     */
    @GetMapping("/sendcode")
    public R sendCode(@RequestParam("phone") String phone, @RequestParam("code")String code){
        smsComponent.sendSmsCode(phone,code);
        return R.ok();
    }
}

2.在auth模块远程调用短信验证码功能

1)新建ThirdPartFeignService

@FeignClient("gulimail-third-party")
public interface ThirdPartFeignService {
    @GetMapping("/sms/sendcode")
    public R sendCode(@RequestParam("phone") String phone, @RequestParam("code")String code);
}

2)随机生成六位随机数字

/**
 * 生成随机数
 */
public class RandomUUID {
    /**
     * 生成六位数字随机数
     * @return
     */
    public static String randomSixNumber(){
        StringBuilder str = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 6 ; i++) {
            //随机生成10以内的数字
            int number = random.nextInt(10);
            str.append(number);
        }
        return str.toString();
    }
}

3)添加发送验证码功能

@Controller
public class LoginController {
    @Autowired
    private ThirdPartFeignService thirdPartFeignService;

    @GetMapping("/sms/sendcode")
    public R sendCode(@RequestParam("phone") String phone){
        //随机生成验证码
        String code = RandomUUID.randomSixNumber();
        thirdPartFeignService.sendCode(phone,code);
        return R.ok();
    }
}

注:随机生成的验证码就是发送到你手机上的验证码

3.测试发送短信验证码

//给指定的手机发送验证码
let phone = $("#phoneNumber").val();
$.get("/sms/sendcode?phone="+phone);

java 短信验证码脱敏 java 短信验证码防刷_redis_06


发送成功

思考:如果刷新页面后,再次获取验证码,就会重置60秒,所以验证码的60s必须是严格意义上的60s。并且需要给验证码设置超时时间。

六:验证码防刷校验,设置过期时间

1)给auth模块引入redis依赖

<!--引入redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2)配置redis地址

spring.redis.host=127.0.0.1
spring.redis.port=6379

3)存储到redis中。key-phone,value-code

@GetMapping("/sms/sendcode")
    @ResponseBody
    public R sendCode(@RequestParam("phone") String phone){
        //1.接口防刷,防止同一个手机号60s内再次发送
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if(!StringUtils.isEmpty(redisCode)){
            long redisDate = Long.parseLong(redisCode.split("_")[1]);
            if(System.currentTimeMillis() - redisDate < 60000){
                //60秒内不可以再发
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(),BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        //随机生成验证码
        String code = RandomUUID.randomSixNumber();
        String dateCode = code + "_" + System.currentTimeMillis();
        //2.验证码的再次校验,存储到redis中。key-phone,value-code
        //key——"sms:code:15648961564"  value-564986
        //保存到redis里面,并设置10分钟超时时间
        stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone,dateCode,10, TimeUnit.MINUTES);
        thirdPartFeignService.sendCode(phone,code);
        return R.ok();
    }
  • key-phone,value-code
  • key-“sms:code:15648961564” value-564986