【EasyPan】项目常见问题解答(自用&持续更新中…)汇总版
CREATE TABLE `email_code` (
`email` varchar(150) NOT NULL COMMENT '邮箱',
`code` varchar(5) NOT NULL COMMENT '验证码',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`status` tinyint(1) DEFAULT NULL COMMENT '0:未使用 1:已使用',
PRIMARY KEY (`email`,`code`) -- 复合主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='邮箱验证码';
设计特点:
@RequestMapping("/sendEmailCode")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO sendEmailCode(HttpSession session,
@VerifyParam(regex = VerifyRegexEnum.EMAIL) String email,
@VerifyParam String checkCode,
@VerifyParam Integer type) {
try {
// 1. 校验图形验证码
if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
throw new BusinessException("图形验证码错误");
}
// 2. 发送邮件验证码
emailCodeService.sendEmailCode(email, type);
return getSuccessResponseVO(null);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL); // 销毁图形验证码
}
}
@Transactional(rollbackFor = Exception.class)
public void sendEmailCode(String email, Integer type) {
// 1. 注册场景校验邮箱唯一性
if (type == Constants.ZERO) {
if (userInfoMapper.selectByEmail(email) != null) {
throw new BusinessException("邮箱已注册");
}
}
// 2. 生成5位数字验证码
String code = StringTools.getRandomNumber(Constants.LENGTH_5);
// 3. 发送邮件
sendMailCode(email, code);
// 4. 失效旧验证码
emailCodeMapper.disableEmailCode(email);
// 5. 存储新验证码
EmailCode emailCode = new EmailCode();
emailCode.setEmail(email);
emailCode.setCode(code);
emailCode.setStatus(Constants.ZERO); // 未使用状态
emailCode.setCreateTime(new Date());
emailCodeMapper.insert(emailCode);
}
private void sendMailCode(String toEmail, String code) {
try {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true); // 支持多部分邮件
// 从Redis获取邮件模板配置
SysSettingsDto settings = redisComponent.getSysSettingsDto();
// 设置邮件基本信息
helper.setFrom(appConfig.getSendUserName());// 发件人
helper.setTo(toEmail);// 收件人
helper.setSubject(settings.getRegisterEmailTitle());// 主题
helper.setText(String.format(settings.getRegisterEmailContent(), code)); // 内容
helper.setSentDate(new Date());// 发送时间
// 触发发送
javaMailSender.send(message);
} catch (Exception e) {
logger.error("邮件发送失败", e);
throw new BusinessException("邮件发送失败");
}
}
防护措施 | 实现方式 |
---|---|
图形验证码校验 | 先校验图形验证码正确性后才允许发送邮件 |
验证码时效性 | 通过create_time字段后续可做有效期校验 |
旧验证码失效 | 发送新验证码前先将该邮箱所有旧验证码标记为失效 |
防重复注册 | 注册场景(type=0)下校验邮箱是否已存在 |
模板注入防护 | 使用String.format规范插入验证码,避免邮件内容拼接 |
/**
* 邮箱验证码表结构
*/
CREATE TABLE `email_code` (
`email` varchar(150) NOT NULL COMMENT '邮箱',
`code` varchar(5) NOT NULL COMMENT '编号',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`status` tinyint(1) DEFAULT NULL COMMENT '0:未使用 1:已使用',
PRIMARY KEY (`email`,`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='邮箱验证码';
/**
* 发送邮箱验证码接口
*/
@RequestMapping("/sendEmailCode")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO sendEmailCode(HttpSession session,
@VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
@VerifyParam(required = true) String checkCode,
@VerifyParam(required = true) Integer type) {
try {
if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
throw new BusinessException("邮箱验证码不正确");
}
//发送邮箱验证码
emailCodeService.sendEmailCode(email, type);
return getSuccessResponseVO(null);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL);
}
}
/**
* 发送邮箱验证码实现
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void sendEmailCode(String email, Integer type) {
if (type == Constants.ZERO) {
UserInfo userInfo = userInfoMapper.selectByEmail(email);
if (userInfo != null) {
throw new BusinessException("邮箱已经存在");
}
}
String code = StringTools.getRandomNumber(Constants.LENGTH_5);
//发送邮箱验证码
sendMailCode(email, code);
//将该邮箱之前的验证码置为无效
emailCodeMapper.disableEmailCode(email);
EmailCode emailCode = new EmailCode();
emailCode.setEmail(email);
emailCode.setCode(code);
emailCode.setCreateTime(new Date());
emailCode.setStatus(Constants.ZERO);
emailCodeMapper.insert(emailCode);
}
/**
* 实际邮件发送方法
*/
private void sendMailCode(String toEmail, String code){
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(appConfig.getSendUserName());
helper.setTo(toEmail);
SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
helper.setSubject(sysSettingsDto.getRegisterEmailTitle());
helper.setText(String.format(sysSettingsDto.getRegisterEmailContent(), code));
helper.setSentDate(new Date());
javaMailSender.send(mimeMessage);
} catch (Exception e) {
logger.error("邮件发送失败", e);
throw new BusinessException("邮件发送失败");
}
}