Springboot+redis实现用户验证码验证

该代码示例展示了如何通过Redis缓存管理邮箱验证码的发送频率,确保30秒内只发送一次。当请求发送验证码时,首先检查Redis中是否存在邮箱作为key的缓存,如果存在且时间戳在有效期内,则提示操作过于频繁。否则,生成新的验证码,通过邮件发送,并将包含验证码和过期时间的数据存储到Redis中。另外,提供了验证验证码的接口,从Redis获取缓存数据并与用户输入的验证码进行比对。
摘要由CSDN通过智能技术生成

思路:key为用户邮箱,value为时间戳,当发送验证码的请求进来先检查是否存在这个key然后将时间戳与当前时间戳比较如果小于验证码发送的时间(比如设置了30s内只能发送一次)则返回"您的操作过于频繁"的提示,否则将key-value设置一定的过期时间存到Redis当中,返回验证码
代码:

    @OpLog(title = "邮箱验证码", businessType = "发送")
    @GetMapping(value = "/send-security-code", produces = "application/json;charset=UTF-8")
    public Result<String> sendSecurityCode(@NotBlank(message = "邮箱不能为空")
                                           @Size(min = 1, max = 50, message = "邮箱长度错误")
                                           @Pattern(regexp = CloudDiskConstantConfiguration.REGULAR_VERIFICATION_EMAIL, message = "邮箱格式错误") String email,
                                           @RequestParam(name = "exist", required = false, defaultValue = "false") Boolean exist,
                                           HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");

        // 如果exist值为true,则需要校验当前邮箱是否存在
        if (exist) {
            Assert.notNull(diskUserService.getDiskUserToModel("userEmail", email), "该账户不存在,请重新输入");
        }

        // 根据邮箱地址尝试获取之前的缓存数据
        String cacheData = redisTemplate.opsForValue().get(email);
        if (StrUtil.isNotBlank(cacheData)) {
            // 缓存的时间戳
            long timestamp = JSONObject.parseObject(cacheData).getLong("timestamp");
            // 时间戳 > 当前的时间戳
            if (timestamp >= System.currentTimeMillis()) {
                return Result.fail("您的操作过于频繁");
            }
        }

        // 生成4位数随机安全码
        String securityCode = RandomUtil.randomStringUpper(4);
        // 邮件发送的标题
        String subject = StrUtil.format("验证码:{}", securityCode);
        // 邮件发送的内容
        String content = String.format(CloudDiskConstantConfiguration.MAIL_TEMPLATE_CONTENT, StrUtil.format("您的验证码为: {}<br/>5 分钟内有效。", securityCode));
        // 配置邮件发送
        MailUtil.send(email, subject, content, true);

        // 将结果存入缓存 构建缓存数据
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("securityCode", securityCode);
        // 获取当前时间偏移1分钟后的时间戳
        jsonObject.put("timestamp", DateUtil.offset(new Date(), DateField.MINUTE, 1).getTime());
        //这个api设置了过期时间,最后一个参数是时间单位
        redisTemplate.opsForValue().set(email, jsonObject.toJSONString(), CACHE_TIME, TimeUnit.MILLISECONDS);
        return Result.ok("验证码已发送");
    }
//校验验证码:
 @OpLog(title = "邮箱验证码", businessType = "校验")

    @GetMapping(value = "/verify-security-code", produces = "application/json;charset=UTF-8")
    public Result<Boolean> verifySecurityCode(@NotBlank(message = "请输入邮箱")
                                              @Size(min = 1, max = 50, message = "邮箱长度错误")
                                              @Pattern(regexp = CloudDiskConstantConfiguration.REGULAR_VERIFICATION_EMAIL, message = "邮箱格式错误") String email,
                                              @NotBlank(message = "请输入验证码")
                                              @Size(min = 1, max = 50, message = "验证码长度错误") String code,
                                              HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");

        // 获取邮箱验证码校验结果
        String validationResult = securityCodeValidation(email, code);
        return Result.ok(validationResult.equals("ok"));
    }
  /**
     * 用户邮箱验证码校验
     *
     * @param userEmail          用户邮箱
     * @param authenticationCode 用户输入的验证码
     * @return 校验失败时返回对应失败的字符串 ,否则返回 Ok
     */
    public String securityCodeValidation(String userEmail, String authenticationCode) {
        // 获取缓存数据中的邮箱验证码
        String cacheData = redisTemplate.opsForValue().get(userEmail);
        if (StrUtil.isBlank(cacheData)) {
            return "验证码已过期,请重新获取";
        }

        // 缓存数据中的验证码
        String securityCode = JSONObject.parseObject(cacheData).getString("securityCode");
        if (!securityCode.equalsIgnoreCase(authenticationCode)) {
            return "验证码无效";
        }

        return "ok";
    }

大致流程就是这些了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是实现步骤: 1. 添加 Redis 依赖 在 `pom.xml` 文件中添加 Redis 依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置 Redis 在 `application.properties` 文件中添加 Redis 相关配置: ```properties # Redis配置 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.database=0 spring.redis.timeout=60000 ``` 3. 编写验证码生成和存储逻辑 编写一个 `VerificationCodeUtil` 工具类,生成验证码并将验证码存储到 Redis 中: ```java @Component public class VerificationCodeUtil { @Autowired private RedisTemplate<String, String> redisTemplate; /** * 生成验证码 * @param key 键 * @param expire 过期时间 * @return 验证码 */ public String generateCode(String key, long expire) { //生成四位数字的验证码 String code = String.format("%04d", new Random().nextInt(9999)); //将验证码存储到 RedisredisTemplate.opsForValue().set(key, code, expire, TimeUnit.SECONDS); return code; } } ``` 4. 编写验证码登录逻辑 编写一个 `LoginController` 控制器,实现验证码登录功能: ```java @RestController public class LoginController { @Autowired private VerificationCodeUtil verificationCodeUtil; @Autowired private RedisTemplate<String, String> redisTemplate; @PostMapping("/login") public String login(String phone, String code) { //从 Redis 中获取验证码 String cacheCode = redisTemplate.opsForValue().get(phone); if (cacheCode == null) { return "验证码已过期,请重新获取"; } if (!cacheCode.equals(code)) { return "验证码错误"; } //验证码验证通过,执行登录逻辑 return "登录成功"; } @GetMapping("/getCode") public String getCode(String phone) { //生成验证码并存储到 Redis 中,有效期为60秒 String code = verificationCodeUtil.generateCode(phone, 60); return code; } } ``` 至此,我们已经实现了使用 Redis 存储验证码实现验证码登录的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值