这里仅给出关键代码
/** * 发送验证码 * 1、匹配图形验证码是否正常 * 2、发送验证码 * * @param to * @param captcha * @return */ @ApiOperation("发送邮箱注册验证码") @GetMapping("send_code") public JsonData sendRegisterCode(@RequestParam(value = "to",required = true) String to, @RequestParam(value = "captcha",required = true) String captcha, HttpServletRequest request){ String key = getCaptchaKey(request); //获取缓存key String cacheCaptcha = redisTemplate.opsForValue().get(key); //匹配图形验证码是否一样 if(captcha !=null && cacheCaptcha !=null && captcha.equalsIgnoreCase(cacheCaptcha)){ //成功 redisTemplate.delete(key); JsonData jsonData = notifyService.sendCode(SendCodeEnum.USER_REGISTER,to); return jsonData; }else{ return JsonData.buildResult(BizCodeEnum.CODE_CAPTCHA_ERROR); } }
import lombok.extern.slf4j.Slf4j; import net.xdclass.enums.BizCodeEnum; import net.xdclass.enums.SendCodeEnum; import net.xdclass.component.MailService; import net.xdclass.service.NotifyService; import net.xdclass.utils.CheckUtil; import net.xdclass.utils.CommonUtil; import net.xdclass.utils.JsonData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @Slf4j public class NotifyServiceImpl implements NotifyService { @Autowired private MailService mailService; /** * 验证码的标题 */ private static final String SUBJECT= "验证码"; /** * 验证码的内容 */ private static final String CONTENT= "您的验证码是%s,有效时间是60秒,打死也不要告诉任何人"; @Override public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) { if(CheckUtil.isEmail(to)){ //邮箱验证码 String code = CommonUtil.getRandomCode(6); mailService.sendMail(to,SUBJECT,String.format(CONTENT,code)); return JsonData.buildSuccess(); } else if(CheckUtil.isPhone(to)){ //短信验证码 } return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR); } }
public interface NotifyService { JsonData sendCode(SendCodeEnum sendCodeEnum, String to ); }
为了避免如果用户疯狂搞你,一直重复请求验证码,所以这里家人防止对面的操作,原理就是,在key的拼接,也就是微服务上说的第三种解决方案,在key生成的时候拼接上时间戳,然后存储到Redis,随后用户请求的时候进行查询,如果时间戳不符合,那么将拒绝发送,这里给出具体代码
/** * 验证码的内容 */ private static final String CONTENT= "您的验证码是%s,有效时间是60秒,打死也不要告诉任何人"; /** * 前置:判断是否重复发送 * * 1、存储验证码到缓存 * * 2、发送邮箱验证码 * * 后置:存储发送记录 * * @param sendCodeEnum * @param to * @return */ @Override public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) { String cacheKey = String.format(CacheKey.CHECK_CODE_KEY,sendCodeEnum.name(),to); String cacheValue = redisTemplate.opsForValue().get(cacheKey); //如果不为空,则判断是否60秒内重复发送 if(StringUtils.isNotBlank(cacheValue)){ long ttl = Long.parseLong(cacheValue.split("_")[1]); //当前时间戳-验证码发送时间戳,如果小于60秒,则不给重复发送 if(CommonUtil.getCurrentTimestamp() - ttl < 1000*60){ log.info("重复发送验证码,时间间隔:{} 秒",(CommonUtil.getCurrentTimestamp()-ttl)/1000); return JsonData.buildResult(BizCodeEnum.CODE_LIMITED); } } //拼接验证码 2322_324243232424324 String code = CommonUtil.getRandomCode(6); String value = code+"_"+CommonUtil.getCurrentTimestamp(); redisTemplate.opsForValue().set(cacheKey,value,CODE_EXPIRED, TimeUnit.MILLISECONDS); if(CheckUtil.isEmail(to)){ //邮箱验证码 mailService.sendMail(to,SUBJECT,String.format(CONTENT,code)); return JsonData.buildSuccess(); } else if(CheckUtil.isPhone(to)){ //短信验证码 } return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR); }
接下来三步走,第一步获取验证码,第二步根据验证码请求发送邮箱验证码,第三步收获成功[aru_17]









本文作者为DBC,转载请注明。