springboot发送短信验证码,结合redis 实现限制,验证码有效期2分钟,有效期内禁止再次发送,一天内发送超3次限制

前言(可忽略)

好久没有更新过csdn博客了,从2023年到发布这篇文章之前,感觉有1年没有写代码的状态,大多还是和 工作/日常 有关 影响,有点退步了。 现在找回了写代码的那种状态,找回状态后发现还是要多学习,要始终保持着热爱 虚心钻研之心.

工作之余想到了一些功能点,空闲时间自己实现了下,做个记录。 有时间还是得要多写点业务代码,不然一直在退步.
----好了 不多说了,进入文章正题---</b>

实现思路

调用发送短信接口,输入手机号发送短信。

发送请求后,判断手机号码格式是否正确,格式不正确,返回格式错误信息。

格式正确,进行发送短信,发送成功时,redis中缓存该手机号验证码2分钟 同时缓存24小时发送次数默认1。

如验证码2分钟未失效,再次使用相同手机号码发短信时,返回验证码在有效期内请勿重复发送。

2分钟验证码失效后,会自动删除该验证码缓存。可再次对该手机号发送验证码,再次发送成功后,该号码24小时发送次数缓存值+1,此时短信发送成功第二次。

24小时内重复发送短信测试,直到达到3次后。 发送验证码返回24小时发送验证码3次,发送失败,请于1天后重试。

正题

使用springboot框架结合redis发送验证码, 实现限制功能,验证码有效期2分钟,有效期内禁止再次发送,一天内发送超3次限制.

代码中定义短信云平台模板,进行模拟发送真实验证码,可接入阿里云等各种第三方云短信模板,结合各种场景进行验证码后续的业务操作。

在这里插入图片描述

// 模拟阿里云发送短信业务, 模板示例值.  可自行对接
String sendMsg = "【提先森的小站】测试阿里云服务短信发送,此次操作验证码为 {} ,该验证码有效期2分钟,请尽快输入验证.";

使用良好优雅的代码规范实现限制发送验证码功能, 加入统一枚举返回错误类型,统一redis缓存key值管理~


以下开始正文 附上效果图示例和完整代码,希望对看到有需要的朋友有所帮助。
如有帮到您,还希望点赞支持一下yo~


效果图示例

手机号不符合规则校验图

在这里插入图片描述

成功发送验证码示例图

在这里插入图片描述

redis中缓存随机数字验证码,2分钟后失效删除redis缓存图

在这里插入图片描述

验证码有效期内 返回禁止重复发送图

在这里插入图片描述

验证码24小时内发送达到3次,限制再次发送验证码图

在这里插入图片描述

idea代码控制台输出日志信息图

在这里插入图片描述

接口压测1万次全部success图

在这里插入图片描述


在这里插入图片描述

使用到的maven依赖

        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--hutool 工具使用参考文档:https://hutool.cn/ -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.20</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>  

redis 缓存Key 统一静态管理类

/**
 * @author zxt
 * @version 1.0.0
 * @date 2023年06月20日 11:29:16
 * @describe redis 缓存Key 统一管理
 */
public class RedisKeyConstant {
   
	// 发送验证码key
    public static final String USER_REGISTER_KEY = "user:register:send_code:{}";
    // 手机号24小时内发送验证码次数key
    public static final String USER_REGISTER_COUNT_KEY = "user:register:day_send_count:{}";


    public static final String USER_INFORMATION_KEY = "user:information:{}";
    public static final Integer USER_INFORMATION_EXPIRED = 3;
    public static final String USER_LOGIN_INFORMATION_KEY = "login:info:{}";
    public static final Integer USER_LOGIN_INFORMATION_EXPIRED = 2;
    public static final String APPLET_TELECOM_TOKEN_KEY = "user:token:{}";
    public static final Integer APPLET_TELECOM_TOKEN_EXPIRED = 1;

}

返回错误信息枚举定义

/**
 * @author zxt
 * @apiNote
 * @date 2024/4/16 10:23
 */
public enum ServiceErrorEnum {
   

    SUCCESS(0, "OK!"),
    SERVER_ERROR(500, "Internal Server Error"),
    PARAM_FAIL(-1, "Param Fail"),

    REGISTER_RECAPTCHA_INPUT_ERROR(10000, "注册失败, 验证码输入错误..."),
    REGISTER_RECAPTCHA_EXPIRE(10001, "注册失败, 手机号验证码信息不存在..."),
    REGISTER_RECAPTCHA_ISVALID(10002, "验证码在有效期内, 2分钟内请勿重复发送... "),
    REGISTER_CODE_COUNT_ERROR(10003, "24小时内已发送验证码3次,发送已限制 请于1天后重试..."),
    REGISTER_PHONENUMBER_ERROR(10004, "请检查手机号码是否符合规范..."),
    REGISTER_PHONENUMBER_ISREGISTER(10006, "短信发送失败,该手机号已注册..."),
    REGISTER_PHONENUMBER_EXIST(10007, "该手机号已注册,注册失败..."),

    LOGIN_PASSWORD_ERROR(10008, "用户名或密码输入错误,登录失败..."),
    LOGIN_NOREGISTER_ERROR(10009, "手机号未注册,登录失败..."),
    ;

    /**
     * code
     */
    private int code;

    /**
     * message
     */
    private String message;


    public int getCode() {
   
        return code;
    }

    public void setCode(int code) {
   
        this.code = code;
    }

    public String getMessage() {
   
        return message;
    }

    public void setMessage(String message) {
   
        this.message = message;
    }

    ServiceErrorEnum(int code, String message) {
   
        this.code = code;
        this.message = message;
    }
}

redis缓存util工具类封装

/**
 * spring redis 工具类
 *
 * @author zxt
 **/
@SuppressWarnings(value = {
    "unchecked", "rawtypes" })
@Component
@Slf4j
public class RedisCache
{
   
    @Resource
    public RedisTemplate redisTemplate;

    private static final Long SUCCESS = 1L;
    private static final Integer DEFAULT_EXPIRE_TIME = 30 * 60;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
   
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
   
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }
    
    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
   
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 判断 key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public Boolean hasKey(String key)
    {
   
        return redisTemplate.hasKey(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
   
        return redisTemplate.delete(key);
    }

}

StringUtils字符 常用操作工具类

package com.tiz.third.utils;

import com.tiz.third.constant.Constants;
import com.tiz.third.core.text.StrFormatter
### Spring Boot 实现发送短信验证码 #### 创建发送短信的服务类 为了实现发送短信验证码,在Spring Boot项目中可以创建一个新的Java类用于处理发送逻辑。此服务类负责生成随机验证码并调用第三方API完成实际的消息传递操作[^1]。 ```java @Service public class SmsService { @Value("${aliyun.sms.templateCode}") private String templateCode; public void sendSms(String phoneNumber) { // Generate a random verification code (e.g., 6 digits) Random r = new Random(); StringBuilder sb = new StringBuilder(6); while(sb.length() < 6){ sb.append(r.nextInt(10)); } String verifyCode = sb.toString(); // Store the generated code into Redis with expiration time set to two minutes. redisTemplate.opsForValue().set(phoneNumber, verifyCode, 2, TimeUnit.MINUTES); // Call AliCloud SMS API here using the provided phone number and template code... System.out.println("Sending SMS: " + phoneNumber + ", Code:" + verifyCode); // For demonstration purposes only // Actual implementation would involve calling an external service like Alibaba Cloud&#39;s SDK or RESTful APIs. } } ``` 该`sendSms()`方法接受电话号码作为输入参数,生成六位数长度的随机字符串作为验证代码,并将其存储在Redis缓存中设置过期时间为两分钟。之后通过调用外部SMS网关(此处假设为阿里云),将消息发送给指定用户[^4]。 #### 注册 Bean 和配置文件 为了让上述组件能够被自动装配进应用程序上下文中,需确保其标记了适当注解(如上面例子中的 `@Service`)。另外还需要定义相应的属性值来填充这些bean实例所需的变量,比如阿里云短信模板ID等信息: ```yaml aliyun: sms: accessKeyId: YOUR_ACCESS_KEY_ID secretAccessKey: YOUR_SECRET_ACCESS_KEY signName: YourSignName templateCode: TEMPLATE_CODE ``` 以上YAML片段展示了部分可能需要配置的关键项;具体取决于所使用的SDK版本以及个人账户详情。 #### 构建控制器暴露HTTP端点 最后一步是在Web层面上构建REST Controller以公开对外接口供前端或其他微服务调用。这里展示了一个简单的GET请求处理器样例,它会触发一新的验证码发送过程[^3]。 ```java @RestController @RequestMapping("/api/v1/sms") public class SmsController { @Autowired private SmsService smsService; @GetMapping("/{phoneNumber}") public ResponseEntity<?> sendVerificationCode(@PathVariable String phoneNumber) throws Exception{ try { Pattern pattern = Pattern.compile("^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$"); Matcher matcher = pattern.matcher(phoneNumber); if (!matcher.matches()) throw new IllegalArgumentException("Invalid Phone Number"); smsService.sendSms(phoneNumber); return ResponseEntity.ok(Map.of("message", "Verification code sent successfully")); } catch(IllegalArgumentException e){ return ResponseEntity.badRequest().body(e.getMessage()); } } } ``` 这段代码实现了基本的身份验证流程控制——首先检查传入手机号是否合法,接着委托给之前提到过的业务逻辑去执行具体的动作。如果一切顺利,则返回成功响应;反之则给出相应提示说明失败原因。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值