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和数据库存储的
- OTP校验通过后,记得把
oneTimePassword字段置空,避免同一个OTP被重复使用 - 如果后续业务逻辑变复杂,可以把OTP生成、存储、校验的逻辑抽离到专门的
OtpService层,当前功能简单直接写在Controller即可正常运行
内容的提问来源于stack exchange,提问作者Harshit Toxia
相关产品推荐
相关产品推荐

