首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Boot 实现登录验证码有效时间

Spring Boot 实现登录验证码有效时间

原创
作者头像
繁依Fanyi
发布2024-09-21 11:28:39
发布2024-09-21 11:28:39
5150
举报

在现代 Web 应用中,为了提高安全性,登录过程中常常会引入验证码(CAPTCHA)以防止恶意的自动化攻击。然而,简单的验证码并不足够,为了进一步增强安全性,我们通常会为验证码设置有效时间,即验证码只能在生成后的某一段时间内使用,过期后需重新获取。在本文中,我们将以 Spring Boot 为例,详细讲解如何实现带有效时间的登录验证码系统。

一、为什么需要验证码有效时间

验证码通常用于防范暴力破解攻击或机器人自动提交表单。但如果验证码的有效期过长,黑客可能有足够的时间通过试探来破解验证码。因此,为了提升安全性,给验证码设定一个合理的有效期是十分必要的。如果验证码过期,用户需要重新生成验证码。这不仅增加了攻击者破解的难度,还能够提高系统的防御能力。

二、项目结构设计

为了实现验证码的有效时间管理,我们可以采取以下步骤:

  1. 生成验证码并将其存储(通常存储在 Redis 之类的缓存系统中)。
  2. 在存储验证码时,将生成时间一同存储。
  3. 当用户提交验证码时,验证验证码的有效性和正确性(包括是否超时)。
  4. 如果验证码过期或者不正确,则返回相应的错误提示。
主要功能模块:
  • 验证码生成与存储
  • 验证码有效时间的检查
  • Redis 作为缓存存储验证码和其生成时间

三、项目依赖

首先,我们需要在 Spring Boot 项目中引入 Redis 的依赖,验证码需要通过 Redis 来进行存储,以支持分布式缓存和高效的读取。

代码语言:xml
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

同时,我们还需要引入验证码生成的工具类库,常用的有 kaptcha 或者 captcha-generator 等:

代码语言:xml
复制
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

四、Redis 配置

接下来,我们需要配置 Redis 连接信息。在 application.yml 中,添加如下配置:

代码语言:yaml
复制
spring:
  redis:
    host: localhost
    port: 6379
    timeout: 6000ms
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

五、验证码生成与存储逻辑

1. 编写验证码生成服务

我们将使用 Kaptcha 来生成图片验证码。首先定义一个 CaptchaService 用于生成验证码:

代码语言:java
复制
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.util.Config;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.awt.image.BufferedImage;
import java.util.Properties;

@Service
public class CaptchaService {

    private Producer kaptchaProducer;

    @PostConstruct
    public void init() {
        Properties properties = new Properties();
        properties.setProperty("kaptcha.border", "no");
        properties.setProperty("kaptcha.textproducer.font.color", "black");
        properties.setProperty("kaptcha.textproducer.char.space", "5");
        Config config = new Config(properties);
        kaptchaProducer = config.getProducerImpl();
    }

    public String createCaptcha() {
        return kaptchaProducer.createText();
    }

    public BufferedImage createCaptchaImage(String captchaText) {
        return kaptchaProducer.createImage(captchaText);
    }
}
2. Redis 存储验证码与有效时间

当生成验证码后,我们将验证码及其生成时间存储到 Redis 中,设置一个过期时间(如5分钟),验证码生成时的时间戳也需要一并存储,以便后续验证。

代码语言:java
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class CaptchaStoreService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final long CAPTCHA_EXPIRE_TIME = 5 * 60; // 5分钟

    public void saveCaptcha(String captchaId, String captchaText) {
        redisTemplate.opsForValue().set(captchaId, captchaText, CAPTCHA_EXPIRE_TIME, TimeUnit.SECONDS);
    }

    public String getCaptcha(String captchaId) {
        return redisTemplate.opsForValue().get(captchaId);
    }

    public boolean deleteCaptcha(String captchaId) {
        return redisTemplate.delete(captchaId);
    }
}

六、验证码验证逻辑

在用户提交验证码时,我们需要检查验证码是否存在、是否过期、是否正确。

代码语言:java
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CaptchaValidationService {

    @Autowired
    private CaptchaStoreService captchaStoreService;

    public boolean validateCaptcha(String captchaId, String captchaInput) {
        String storedCaptcha = captchaStoreService.getCaptcha(captchaId);

        if (storedCaptcha == null) {
            // 验证码不存在或已过期
            return false;
        }

        return storedCaptcha.equalsIgnoreCase(captchaInput);
    }
}

七、Controller 层实现

为了将上述逻辑整合到系统中,我们需要编写一个控制器来生成并验证验证码。

1. 生成验证码的接口
代码语言:java
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

@RestController
public class CaptchaController {

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private CaptchaStoreService captchaStoreService;

    @GetMapping("/captcha/{captchaId}")
    public void getCaptcha(@PathVariable String captchaId, HttpServletResponse response) throws IOException {
        String captchaText = captchaService.createCaptcha();
        captchaStoreService.saveCaptcha(captchaId, captchaText);
        BufferedImage image = captchaService.createCaptchaImage(captchaText);
        response.setContentType("image/jpeg");
        ImageIO.write(image, "jpg", response.getOutputStream());
    }
}
2. 验证验证码的接口
代码语言:java
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {

    @Autowired
    private CaptchaValidationService captchaValidationService;

    @PostMapping("/login")
    public String login(@RequestParam String captchaId, @RequestParam String captchaInput) {
        boolean isCaptchaValid = captchaValidationService.validateCaptcha(captchaId, captchaInput);
        
        if (!isCaptchaValid) {
            return "验证码错误或已过期";
        }

        // 执行后续登录逻辑...
        return "登录成功";
    }
}

八、使用 Redis 实现验证码过期管理

Redis 提供了对键值的过期时间设置功能,在生成验证码时,我们将其存入 Redis 并设置一个过期时间。这种方法简洁且高效,特别适用于分布式系统。每次验证码生成时,Redis 会自动删除过期的验证码数据,保证不会有冗余信息存留。

在我们的代码中,我们通过 StringRedisTemplateopsForValue() 方法,将验证码存储到 Redis 并设定其存活时间。当用户提交验证码进行验证时,首先检查 Redis 中是否存在该验证码,若不存在则表明验证码已过期。

十、总结

通过本文的详细介绍,我们使用 Spring Boot 搭建了一个带有效时间的验证码登录系统。整个过程包括了验证码的生成、存储、有效时间的设定、验证等步骤。通过 Redis 的过期时间特性,轻松实现了验证码的有效期控制。这种方法适用于大多数应用场景,并且具有较高的安全性和可扩展性。在实际生产环境中,还可以根据业务需求对验证码的生成方式、存储策略、验证逻辑等做进一步优化。

总的来说,验证码的引入和有效时间控制是 Web 应用安全体系中的重要环节。通过合理的配置和实现,可以显著提升系统对暴力破解和恶意攻击的防御能力。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么需要验证码有效时间
  • 二、项目结构设计
    • 主要功能模块:
  • 三、项目依赖
  • 四、Redis 配置
  • 五、验证码生成与存储逻辑
    • 1. 编写验证码生成服务
    • 2. Redis 存储验证码与有效时间
  • 六、验证码验证逻辑
  • 七、Controller 层实现
    • 1. 生成验证码的接口
    • 2. 验证验证码的接口
  • 八、使用 Redis 实现验证码过期管理
  • 十、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档