You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot项目中如何实现生成的邮件OTP验证码数据库存储

OTP数据库存储实现方案

你需要在OtpEmailController的/send-otp接口中编写存储逻辑,必须在调用邮件发送方法前完成数据库存储,避免出现邮件发送成功但数据库存储失败的不一致问题。具体实现步骤如下:


1. 先修复现有代码的基础问题

你当前的代码有两个影响OTP功能正常使用的bug,需要先修复:

  • Random random = new Random(1000)使用了固定种子,生成的随机数序列是固定可预测的,完全起不到验证码安全作用,要改成无参构造new Random()
  • 直接用nextInt(999999)生成的数字可能不足6位(比如生成123实际是3位),需要补前导零固定为6位字符串

2. 补全实体类的访问方法

你的SessionHandling实体类目前只定义了字段,需要补充OTP相关字段的setter/getter方法,否则无法对字段赋值、读取:

// 将以下方法补充到SessionHandling实体类中
public String getOneTimePassword() {
    return oneTimePassword;
}

public void setOneTimePassword(String oneTimePassword) {
    this.oneTimePassword = oneTimePassword;
}

public Date getOtpRequestedTime() {
    return otpRequestedTime;
}

public void setOtpRequestedTime(Date otpRequestedTime) {
    this.otpRequestedTime = otpRequestedTime;
}

3. 注入Repository依赖

在OtpEmailController中注入你已经定义好的SessionHandlingRepository,用于执行数据库操作:

@Autowired
private SessionHandlingRepository sessionHandlingRepository;

4. 编写OTP存储核心逻辑

在生成OTP之后、发送邮件之前,按以下流程编写逻辑:

  • 根据传入的邮箱查询对应用户记录,不存在则直接返回错误
  • 给查询到的用户实体设置OTP值、OTP请求时间(取当前系统时间)
  • 调用JPA的save方法将更新后的用户记录存入数据库
  • 数据库存储成功后,再调用邮件服务发送OTP邮件

修改完成后的sendOtp方法参考代码:

@PostMapping("/send-otp")
public String sendOtp(@RequestParam("email") String email) {
    // 生成安全的6位OTP
    Random random = new Random();
    String otp = String.format("%06d", random.nextInt(999999));

    // 查询邮箱对应用户
    SessionHandling targetUser = sessionHandlingRepository.findByEmailId(email);
    if (targetUser == null) {
        return "error"; // 替换为你的错误页逻辑,提示邮箱未注册
    }

    // 更新用户的OTP相关字段
    targetUser.setOneTimePassword(otp);
    targetUser.setOtpRequestedTime(new Date());

    // 存储更新到数据库
    sessionHandlingRepository.save(targetUser);

    // 存储成功后再发送邮件
    String subject = "OTP from session-handling-proj By Harshit";
    String mailBody = "<h1> OTP = " + otp + "</h1>";
    emailService.sendMail(email, subject, mailBody);

    return "success";
}

实现注意事项

  • 不要把OTP存储逻辑写到EmailSenderService中,这个服务的单一职责是发送邮件,不要耦合数据库操作
  • 后续编写OTP校验逻辑时,需要同时校验两个条件:
    • 用户输入的OTP和数据库存储的oneTimePassword完全一致
    • 当前时间与otpRequestedTime的差值不超过你定义的5分钟有效期
  • OTP校验通过后,记得把oneTimePassword字段置空,避免同一个OTP被重复使用
  • 如果后续业务逻辑变复杂,可以把OTP生成、存储、校验的逻辑抽离到专门的OtpService层,当前功能简单直接写在Controller即可正常运行

内容的提问来源于stack exchange,提问作者Harshit Toxia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:57:23