如何在后台实现电子邮件注册 + 验证码 + 防抓取功能
最编程
2024-04-28 13:27:27
...
框架引入,需要引入验证码框架和邮箱服务框架,用Springboot整合所以带有stater,邮箱注册需要防止盗刷,所以需要引入验证码框架,需要防止多次请求,所以选用redis
<dependency> <groupId>com.baomidou</groupId> <artifactId>kaptcha-spring-boot-starter</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>2.3.3.RELEASE</version> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
jedis性能比RedisTemplate的性能好3倍,并且随着数据量的增大,倍数也成指数增加
因此优先选择jedis
,因为他在性能方面完胜RedisTemplate
邮箱服务配置,通过网易申请申请得到,一些邮箱相关的信息,配置Application文件
spring: mail: host: smtp.126.com //发送邮件服务器 username: xxxx@126.com //邮箱 password: xxxxxxx //客户端授权码 千万注意这个不是密码 是客户端授权码 from: xxxx@126.com // properties.mail.smtp.starttls.enable: true properties.mail.smtp.starttls.required: true properties.mail.smtp.ssl.enable: true //开启ssl default-encoding: utf-8 //编码utf-8
redis:
host: xxx.xxx.xxx.xxx
port: xxxx
password: xxxx
验证码的配置
@Configuration public class CaptchaConfig { @Bean @Qualifier("captchaProducer") //重新命名Bean public DefaultKaptcha defaultKaptcha(){ DefaultKaptcha kaptcha = new DefaultKaptcha(); Properties properties = new Properties(); // properties.setProperty(Constants.KAPTCHA_BORDER, "yes"); // properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "220,220,220"); // //properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "38,29,12"); // properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "147"); // properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "34"); // properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "25"); // //properties.setProperty(Constants.KAPTCHA_SESSION_KEY, "code"); //验证码个数 properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); // properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Courier"); //字体间隔 properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8"); //干扰线颜色 // properties.setProperty(Constants.KAPTCHA_NOISE_COLOR, "white"); //干扰实现类 properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); //图片样式 properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.WaterRipple"); //文字来源 properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789"); Config config = new Config(properties); kaptcha.setConfig(config); return kaptcha; } }
发送验证码,防止重复请求验证码
public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) { String cacheKey = String.format(CacheKey.CHECK_CODE_KEY,sendCodeEnum.name(),to); String cacheValue = redisTemplate.opsForValue().get(cacheKey); log.info(cacheValue);
//二次进入 if(cacheValue!=null){ long ttl =Long.parseLong(cacheValue.split("_")[1]); if(CommonUtil.getCurrentTimestamp()-ttl<1000*60){ log.info("重复发送验证码,时间间隔为:{}秒",(CommonUtil.getCurrentTimestamp()-ttl)/1000); return JsonData.buildResult(BizCodeEnum.CODE_LIMITED); } } String code = CommonUtil.getRandomCode(6); String value = code +"_" +CommonUtil.getCurrentTimestamp(); redisTemplate.opsForValue().set(cacheKey,value,CODE_EXPIRED, TimeUnit.MILLISECONDS); if(CheckUtils.isEmail(to)){ mailService.sendEmail(to,SUBJECT,String.format(CONTENT,code)); return JsonData.buildSuccess(); }else if(CheckUtils.isPhone(to)) { } return JsonData.buildSuccess(); }
注册功能
public JsonData register(UserRegisterRequest registerRequest) { boolean checkCode= false; if( registerRequest.getMail()!=null){ checkCode = notifyService.checkCode(SendCodeEnum.USER_REGISTER,registerRequest.getMail(),registerRequest.getCode()); } if(!checkCode){ return JsonData.buildResult(BizCodeEnum.CODE_ERROR); } UserDO userDO = new UserDO(); BeanUtils.copyProperties(registerRequest,userDO); userDO.setCreateTime(new Date()); userDO.setSlogan("xxxxx"); userDO.setSecret("$1$"+ CommonUtil.getRandomCode(8)); String cryPwd= CommonUtil.MD5(registerRequest.getPwd()+userDO.getSecret()); userDO.setPwd(cryPwd); if(checkUnique(userDO.getMail())){ int rows =userMapper.insert(userDO); log.info("rows={},注册成功:{}",rows,userDO.toString()); return JsonData.buildSuccess(); }else{ return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT); } }
controller层
@Autowired private Producer captchaProducer; @Autowired private StringRedisTemplate redisTemplate; @Autowired NotifyService notifyService; private static final long CAPTCHA_CODE_EXPIRED= 60*1000*10; @GetMapping("captcha") public void getCaptcha(HttpServletRequest request, HttpServletResponse response){ String captchaText=captchaProducer.createText(); log.info("图形验证码:{}",captchaText); redisTemplate.opsForValue().set(getCaptchaKey(request),captchaText,CAPTCHA_CODE_EXPIRED, TimeUnit.MILLISECONDS); BufferedImage bufferedImage = captchaProducer.createImage(captchaText); ServletOutputStream outputStream =null; try{ outputStream =response.getOutputStream(); ImageIO.write(bufferedImage,"jpg",outputStream); outputStream.flush(); outputStream.close(); }catch (IOException e){ log.error("获取图形验证码异常{}",e); } } @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); String cacheCaptcha =redisTemplate.opsForValue().get(key); log.info("heheee"); if(captcha!=null &&captcha!=null &&captcha.equalsIgnoreCase(cacheCaptcha)){ redisTemplate.delete(key); JsonData jsonData = notifyService.sendCode(SendCodeEnum.USER_REGISTER,to); return jsonData; }else{ return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR); } } private String getCaptchaKey(HttpServletRequest request){ String ip= CommonUtil.getIpAddr(request); String userAgent=request.getHeader("User-Agent"); String key="user-service:captcha"+ip+CommonUtil.MD5(ip+userAgent); log.info("ip= {}",ip); log.info("userAgent={}",userAgent); log.info("key={}",key); return key; }
邮箱代码编写
@Service @Slf4j public class MailServiceImpl implements MailService { @Autowired JavaMailSender javaMailSender; @Value("${spring.mail.from}") private String from; @Override public void sendEmail(String to,String subject,String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(from); message.setTo(to); message.setSubject(subject); message.setText(content); javaMailSender.send(message); log.info( "邮箱发送成功 {}",message); } }
后端测试结果
总结:redis 首先存储 map<key,value> 首先是 <user-service:captcha:ip+md5(ip+ugent),图形验证码> 然后是map<code:%s:%s,邮箱验证码+当前时间轴> 第一个%s是USER_REGISTER,第二个是要发送的邮箱
代码百度云: 把application文件删除 需要自己配置数据库 redis mail
链接:https://pan.baidu.com/s/1ejwAQ-MnmJGhakXouscXKA
提取码:gcwu
--来自百度网盘超级会员V4的分享
欢迎讨论 +Q3378404370
上一篇: JavaMail 实现注册邮箱验证案例
下一篇: Python3 SMTP发送邮件 |