作者:红烧大青虫 | 来源:互联网 | 2023-08-21 06:38
谷粒商城 注册验证码防盗刷
html
发送验证码
后台代码
/*** 获取短信验证码* @param phone* @return*/@ResponseBody@GetMapping("/sms/sendcode")public R sendCode(@RequestParam("phone") String phone){//TODO 1、接口防刷。String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);if(!StringUtils.isEmpty(redisCode)){long l = Long.parseLong(redisCode.split("_")[1]);if(System.currentTimeMillis() - l <60000){//60秒内不能再发return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(),BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());}}//2、验证码的再次校验。redis。存key-phone,value-code sms:code:17512080612 -> 45678String code = UUID.randomUUID().toString().substring(0, 5);String substring = code+"_"+System.currentTimeMillis();//redis缓存验证码,防止同一个phone在60秒内再次发送验证码redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX+phone,substring,10, TimeUnit.MINUTES);thirdPartFeignService.sendCode(phone,code);return R.ok();}@PostMapping("/regist")public String regist(@Valid UserRegistVo vo, BindingResult result,RedirectAttributes redirectAttributes,HttpSession session){if(result.hasErrors()){Map errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));redirectAttributes.addFlashAttribute("errors",errors);return "redirect:http://auth.gulimall.com/reg.html";}//1、校验验证码String code = vo.getCode();String s = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());if(!StringUtils.isEmpty(s)){if(code.equals(s.split("_")[0])){//删除验证码;令牌机制redisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());//验证码通过。 //真正注册。调用远程服务进行注册R r = memberFeignService.regist(vo);if(r.getCode() == 0){//成功return "redirect:http://auth.gulimall.com/login.html";}else{Map errors = new HashMap<>();errors.put("msg",r.getData("msg",new TypeReference(){}));redirectAttributes.addFlashAttribute("errors",errors);return "redirect:http://auth.gulimall.com/reg.html";}}else{Map errors = new HashMap<>();errors.put("code","验证码错误");redirectAttributes.addFlashAttribute("errors",errors);return "redirect:http://auth.gulimall.com/reg.html";}}else {Map errors = new HashMap<>();errors.put("code","验证码错误");redirectAttributes.addFlashAttribute("errors",errors);//校验出错,转发到注册页return "redirect:http://auth.gulimall.com/reg.html";}}
思路:前端设置60秒倒计时,但是刷新页面仍旧会发送请求,
所以想着把这个code存入redis,时间十分钟过期。首先判断是否过期,也就是是否为空,空的话证明上次已过期或者还没有点击过,就发;
不空的话判断是否大于10秒,如果小于就报错"60秒之内不可以重复发送",如果大于就可以重新发送。
同时,把前台验证码和redis存储的验证码是否一致,若一致,用过一次就删除,令牌机制。下次,再带着老令牌就不好使了。
还有一点需要注意,如果仔细观察redis的key,你会发现是拼接了当时的手机号,这一点非常重要,因为注册的时候,也是取出了注册的手机号这个当key,从而寻找对应的value。