后端如何實現郵箱注冊+驗證碼+防刷功能


框架引入,需要引入驗證碼框架和郵箱服務框架,用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





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM