Spring Boot 3.x 基于 Redis 实现邮箱验证码认证

文章目录

依赖配置

xml 复制代码
<dependencies> 
    <!-- Spring Boot Starter Web --> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    
    <!-- Redis 集成依赖  -->  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-data-redis</artifactId>  
        <version>3.4.2</version>  
    </dependency>  
    
    <dependency>  
        <groupId>org.apache.commons</groupId>  
        <artifactId>commons-pool2</artifactId>  
        <version>2.11.1</version>  
    </dependency>  
    
    <dependency>  
        <groupId>io.lettuce</groupId>  
        <artifactId>lettuce-core</artifactId>  
        <version>6.3.2.RELEASE</version>  
    </dependency>
    
    <!-- 邮件发送支持 --> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-mail</artifactId> 
    </dependency> 
    
    <!-- 验证码生成工具 --> 
    <dependency> 
        <groupId>commons-lang</groupId> 
        <artifactId>commons-lang</artifactId> 
        <version>2.6</version> 
    </dependency>
</dependencies>

开启 QQ 邮箱 SMTP 服务

  1. 打开浏览器,登录到 QQ 邮箱。
  2. 点击左上角的齿轮按钮,进入设置页面,见下图:
    4. 在设置中找到"第三方服务",激活 IMAP/SMTP(默认为禁用),并生成独立的 SMTP 授权码。

配置文件

yaml 复制代码
spring:  
  data:  
    redis:  
      host: your_redis_host
      port: your_redis_port # 通常为6379
      password: your_redis_password
      lettuce:  
        pool:  
          max-active: 8 # 最大连接数  
          max-idle: 8 # 最大空闲连接数  
          min-idle: 0 # 最小空闲连接数  
          max-wait: 100 # 连接等待时间  
  mail:  
    host: smtp.qq.com  
    port: 465  
    username: your_qq_account@qq.com
    password: 111 # 输入 QQ 邮箱的授权码
    properties:  
      mail:  
        smtp:  
          ssl:  
            enable: true  # QQ 邮箱需要开启 SSL
          auth: true

代码实现

验证码服务

使用 Redis 缓存验证码并实现验证码的校验功能:

java 复制代码
@Service  
public class CaptchaService {  
  
    @Autowired  
    private StringRedisTemplate redisTemplate;  
  
    /**  
     * 生成验证码  
     * @param email 目标邮箱  
     * @return 生成的验证码  
     */  
    public String generateCaptcha(String email) { 
        // 生成验证码  
        String code = RandomStringUtils.randomNumeric(6);  
        redisTemplate.opsForValue().set(  
                "CAPTCHA:" + email,  
                code,  
                Duration.ofMinutes(5)  // 验证码有效期为5分钟  
        );  
        return code;  
    }  
  
    /**  
     * 验证码校验  
     * @param email 邮箱  
     * @param code 验证码  
     * @return 是否验证通过  
     */  
    public boolean validateCaptcha(String email, String code) {  
        String captcha = redisTemplate.opsForValue().get("CAPTCHA:" + email);  
        return captcha != null && captcha.equals(code);  
    }  
}

邮件服务

java 复制代码
@Service  
public class EmailService {  
  
    @Autowired  
    private JavaMailSender mailSender;  
  
    /**  
     * 发送验证码邮件  
     * @param email 收件人邮箱  
     * @param authCode 验证码  
     */  
    public void sendCaptchaEmail(String email, String authCode) {  
        SimpleMailMessage message = new SimpleMailMessage();  
        message.setFrom("your_qq_account@qq.com");  
        message.setTo(email);  
        message.setSubject("验证码");  
        message.setText("您的验证码是:" + authCode + ",有效期为5分钟");  
        mailSender.send(message);  
    }
}

接口实现

java 复制代码
@RestController  
public class AuthController {  
  
    @Autowired  
    private UserService userService;  
  
    @Autowired  
    private CaptchaService captchaService;  
  
    @Autowired  
    private EmailService emailService;  
  
    /**  
     * 注册接口  
     * @param userDTO 用户信息  
     * @param captcha 验证码  
     * @return 注册结果  
     */  
    @PostMapping("/register")  
    public Result register(@RequestBody UserDTO userDTO, @RequestParam String captcha) {  
        if (!captchaService.validateCaptcha(userDTO.getEmail(), captcha)) {  
            return Result.error("验证码错误");  
        }  
        userService.register(userDTO);  
        return Result.success();  
    }  
  
    /**  
     * 登录接口  
     * @param userDTO 用户信息  
     * @return 登录结果  
     */  
    @PostMapping("/login")  
    public Result login(@RequestBody UserDTO userDTO) {  
        User user = userService.login(userDTO);  
        if (user == null) {  
            return Result.error("用户不存在");  
        }  
        // 登录成功,生成 JWT 令牌  
        Map<String, Object> claims = new HashMap<>();  
        claims.put("userId", user.getId());  
        String token = JwtUtils.createJWT("secretKey", 60000, claims);  
        UserVO userVO = new UserVO();  
        BeanUtils.copyProperties(user, userVO);  
        LoginResponse loginResponse = new LoginResponse(userVO, token);  
        return Result.success(loginResponse);  
    }  
  
    /**  
     * 发送验证码接口  
     * @param email 邮箱地址  
     * @return 发送结果  
     */  
    @PostMapping("/send-code")  
    public Result sendCode(@RequestParam String email) throws MessagingException {  
        // 校验邮箱格式
        if (!RegexUtils.isEmailValid(email)) {  
            return Result.error("邮箱格式非法");  
        }  
        String code = captchaService.generateCaptcha(email);  
        emailService.sendCaptchaEmail(email, code);  
        return Result.success();  
    }  
}

执行流程

  1. 用户输入邮箱,调用 /send-code 接口获取验证码。
  2. 用户填写验证码并调用 /register 接口进行注册。
  3. 系统校验验证码,验证成功则注册,失败则返回错误信息。
相关推荐
听风同学7 分钟前
RAG的灵魂-向量数据库技术深度解析
后端·架构
橙序员小站11 分钟前
搞定系统面试题:如何实现分布式Session管理
java·后端·面试
老青蛙19 分钟前
权限系统设计-功能设计
后端
粘豆煮包19 分钟前
脑抽研究生Go并发-1-基本并发原语-下-Cond、Once、Map、Pool、Context
后端·go
叫我阿柒啊19 分钟前
从Java全栈到Vue3实战:一次真实面试中的技术探索
java·数据库·spring boot·微服务·typescript·vue3·restful
IT_陈寒1 小时前
Vite5.0性能翻倍秘籍:7个极致优化技巧让你的开发体验飞起来!
前端·人工智能·后端
Edward.W1 小时前
用 Go + HTML 实现 OpenHarmony 投屏(hdckit-go + WebSocket + Canvas 实战)
开发语言·后端·golang
努力努力再努力wz1 小时前
【c++进阶系列】:万字详解AVL树(附源码实现)
java·运维·开发语言·c++·redis
南囝coding2 小时前
Claude 封禁中国?为啥我觉得是个好消息
前端·后端
六边形工程师2 小时前
Docker安装神通数据库ShenTong
后端