短链平台开发-短信验证码和图形验证码编写接口实现

文章介绍了如何在Java应用中使用Redis存储和管理验证码,包括生成验证码、存储策略以及防止短时间内重复发送短信验证码。同时提到了在实现过程中遇到的问题和解决方案,如手机验证规则的更新和正确的短信发送URL配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先图片验证码已经在生成的时候就存入redis了

图形验证码代码如下:

/**
     * 生成验证码
     * @param request
     * @param response
     */
    @GetMapping("/captcha")
    public void getCaptcha(HttpServletRequest request, HttpServletResponse response){
        String capcheaText = capcheaProducer.createText();
        log.info("验证码内容为:{}",capcheaText);
        //存储到redis中,配置过期时间 TODO
        redisTemplate.opsForValue().set(getCaptchaKey(request),capcheaText, CAPTCHA_KEY_TIMEOUT, TimeUnit.MILLISECONDS);
        BufferedImage bufferedImage = capcheaProducer.createImage(capcheaText);
        try(ServletOutputStream outputStream = response.getOutputStream();) {
            ImageIO.write(bufferedImage,"jpg",outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("获取流出错:{}",e.getMessage());
        }

    }

    private String getCaptchaKey(HttpServletRequest request) {
        String ip = CommonUtil.getIpAddr(request);
        String userAgent = request.getHeader("User-Agent");
        String captchaKey = "account-service:captcha:" + CommonUtil.MD5(ip + userAgent);
        log.info("验证码key是:{}",captchaKey);
        return captchaKey;
    }

短信验证码接口实现

需求:一定时间内禁止重复发送验证码

方式一:前端设置校验倒计时按钮,不到60s按钮不准点击(不安全,可以直接请求接口,否决)

方式二:增加redis存储,发送的时候设置额外的key,并且60s后过期(非原子操作,存在不一致,增加额外的key,value存储,浪费空间)

方式三:基于原先的key拼装时间戳 好处 满足了当前节点内的原子性,也满足业务需求

两个时间要求:
 60s后才可以重新发送短信验证码(存入redis的值格式为:"验证码_"+时间戳)
 发送的短信验证码10分钟内有效

具体实现代码如下:

@Override
    public JsonData sendSMS(SendCodeEnum sendCodeEnum , String to) {
        String captchaKey = String.format(RedisKey.CHECK_CODE_KEY, sendCodeEnum.name(), to);
        String captchavalue = stringRedisTemplate.opsForValue().get(captchaKey);

        //如果值不为空,在判断是否是60s重复发送
        if (StringUtils.isNotBlank(captchavalue)){
            long ttl = Long.parseLong(captchavalue.split("_")[1]);
            //当前时间戳-验证码发送的时间戳,如果小于60s,则不给重复发送]
            long leftTime = CommonUtil.getCurrentTimestamp() - ttl;
            if(  leftTime< (1000*60)){
                log.info("重复发送短信验证码,时间间隔:{}s",leftTime);
                return JsonData.buildSuccess(BizCodeEnum.CODE_LIMITED);
            }
        }


        String code = CommonUtil.getRandomCode(6);
        //生成拼接验证码
        String value = code+"_"+CommonUtil.getCurrentTimestamp();
        stringRedisTemplate.opsForValue().set(captchaKey,value,CODE_EXPIRED, TimeUnit.MILLISECONDS);
        
        if (CheckUtil.isEmail(to)){
            //发送邮箱验证码
        }else if (CheckUtil.isPhone(to)){
            //发送手机号验证码
            smsComponent.send(to,smsConfig.getTemplateId(),code);
        }
        return JsonData.buildSuccess();
    }

踩坑:会报错两个位置

解决问题:手机校验规则得更新 发送短信验证码连接请用请求http协议

校验规则代码如下:

package net.xdclass.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author tt
 * @Date 2024/4/2 19:51
 * @PackageName:net.xdclass.util
 * @ClassName: CheckUtil
 * @Description: TODO
 */
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])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\\d{8}$");



    public static boolean isEmail(String email) {
        if (null == email || "".equals(email)) {
            return false;
        }
        Matcher m = MAIL_PATTERN.matcher(email);
        return m.matches();
    }

    public static boolean isPhone(String phone){

        if (phone ==null ||  "".equals(phone)){
            return false;
        }

        Matcher m = PHONE_PATTERN.matcher(phone);
        return m.matches();

    }
}

SmsComponent组件中修改url

private static final String URL_TEMPLATE = "http://jmsms.market.alicloudapi.com/sms/send?mobile=%s&templateId=%s&value=%s";

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值