qq邮箱验证登录注册

目录

🥓1.邮箱注册controller层

🌭2.service实现类

🍿3.工具类 

🥞4.验证码防刷方案 


这篇文章之前,看一下qq验证码文章:http://t.csdnimg.cn/7hnpz

1.邮箱注册controller层

  • 1.根据ip解析,获取key
  • 2.根据key从redis中获取验证码
  • 3.判断前端验证码是否与redis中的一致
  • 4.删除key
  • 5.给邮箱发送注册验证码
 /**
     * redis
     */
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private NotifyService notifyService;


    @ApiOperation("发送邮箱注册验证码")
    @GetMapping("/send_code")
    public JsonData sendRegisterCode(@RequestParam(value = "to", required = true) String to,
                                     @RequestParam(value = "captcha", required = true) String captcha,
                                     HttpServletRequest request) {

        //1.根据浏览器获取key
        String key = getCaptchaKey(request);
        //2.根据key从浏览器获取验证码
        String captchaKey = redisTemplate.opsForValue().get(key);
        //3.判断前端返回的验证码是否与redis中一致
        if (captcha != null && captchaKey != null && captchaKey.equalsIgnoreCase(captcha)) {
            //相等
            //删除key
            redisTemplate.delete(key);
            //注册
            JsonData jsonData = notifyService.sendCode(SendCodeEnum.USER_REGISTER, to);
            log.info("发送成功");
            return JsonData.buildSuccess(jsonData);
        } else {
            //不相等
            return JsonData.buildResult(CodeEnum.CODE_CAPTCHA_ERROR);
        }
    }

2.service实现类

  • 1.判断邮箱或手机号是否合规
  • 2.根据工具类,指定随机验证码的位数
  • 3.调用邮箱发送接口,发送验证码
@Slf4j
@Service
public class NotifyServiceImpl implements NotifyService {


    @Autowired
    private MailService mailService;


    private static final String SUBJECT = "欢迎查收小张的邮箱~";
    private static final String CONTENT = "你的验证码%s,有效时间60秒,悄悄地哦";

    /**
     * 发送验证码
     *
     * @param sendCodeEnum:发送类型
     * @param to:收件人邮箱
     * @return
     */
    @Override
    public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {
        //1.判断是否合规
        if (CheckUtil.isEmail(to)) {
            //指定邮箱验证的位数
            String randomCode = CommonUtil.getRandomCode(6);
            //发送随机验证码
            mailService.sendMail(to, SUBJECT, String.format(CONTENT, randomCode));
            return JsonData.buildSuccess("发送随机验证成功~");
        } else {
            return JsonData.buildResult(CodeEnum.CODE_TO_ERROR);
        }
    }
}

3.工具类 

校验邮箱电话号码是否合规,以及获取ip、md5加密、获取随机验证码

/**
 * 工具类,校验
 */
public class CheckUtil {


    /**
     * 邮箱正则
     */
    private static final Pattern MAIL_PATTERN = Pattern.compile("^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$");

    /**
     * 手机号正则
     */
    private static final Pattern PHONE_PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$");

    /**
     * 邮箱校验
     *
     * @param email
     * @return
     */
    public static boolean isEmail(String email) {
        if (null == email || "".equals(email)) {
            return false;
        }
        Matcher m = MAIL_PATTERN.matcher(email);
        return m.matches();
    }

    /**
     * 手机校验
     *
     * @param phone
     * @return
     */
    public static boolean isPhone(String phone) {
        if (null == phone || "".equals(phone)) {
            return false;
        }
        Matcher m = PHONE_PATTERN.matcher(phone);
        return m.matches();

    }
    /**
     * 获取ip
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) {
                // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        return ipAddress;
    }


    /**
     * MD5加密
     *
     * @param data
     * @return
     */
    public static String MD5(String data) {
        try {
            java.security.MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }

            return sb.toString().toUpperCase();
        } catch (Exception exception) {
        }
        return null;
    }

    /**
     * 获取验证码随机数
     *
     * @param length
     * @return
     */
    public static String getRandomCode(int length) {
        String source = "0123456789";
        Random random = new Random();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            stringBuilder.append(source.charAt(random.nextInt(9)));
        }
        return stringBuilder.toString();
    }

    /**
     * 获取当前时间戳
     *
     * @return
     */
    public static Long getCurrentTimestamp() {
        return  System.currentTimeMillis();
    }
}

4.验证码防刷方案 

  • 1.前端增加校验倒计时,不到60秒按钮不给点击
  • 2.增加Redis存储,发送的时候设置下额外的key,并且60秒后过期
  • 3.基于原先的key拼装时间戳

方案二:使用redis缓存,防刷验证码 

  • 1.根据发送人和类型,获取缓存key
  • 2.根绝获取到的缓存key,从redis中获取value
  • 3.判断value是否为空,
    • 如果不为空,利用  _ 分割获取的value,拿到时间戳,当前时间戳-获取到的如果小于60s则不让其发送
    • 如果为空,则将获取到的验证码拼接时间戳作为value,设置过期时间存储到缓存redis中
/**
     * 发送验证码
     *
     * @param sendCodeEnum:发送类型
     * @param to:收件人邮箱
     * @return
     */
    @Override
    public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {

        //获取缓存key
        String cacheKey = String.format(CaptchaKey.CAPTCHA_CODE_KEY, sendCodeEnum.name(), to);
        //根据key获取value
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        //如果不为空,则判断60秒内重复发送
        if (StringUtils.isNotBlank(cacheValue)) {
            long ttl = Long.parseLong(cacheValue.split("_")[1]);
            //当前时间戳-验证码发送时间错,如果小于60,不重复发送
            if (CommonUtil.getCurrentTimestamp() - ttl < 1000 * 60){
                log.info("重复发送验证码,时间间隔:{}秒",(CommonUtil.getCurrentTimestamp() - ttl)/1000);
                return JsonData.buildResult(CodeEnum.CODE_LIMITED);
            }
        }

        //获取随机验证码
        String randomCode = CommonUtil.getRandomCode(6);
        //获取到的验证码拼接上时间戳
        String value = randomCode + "_" + CommonUtil.getCurrentTimestamp();
        //将拼接后的验证码存到redis中
        redisTemplate.opsForValue().set(cacheKey, value, CODE_EXPIRED, TimeUnit.MILLISECONDS);
        //1.判断是否合规
        if (CheckUtil.isEmail(to)) {
            //指定邮箱验证的位数
            //发送随机验证码
            mailService.sendMail(to, SUBJECT, String.format(CONTENT, randomCode));
            return JsonData.buildSuccess("发送随机验证成功~");
        } else {
            return JsonData.buildResult(CodeEnum.CODE_TO_ERROR);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会敲代码的小张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值