栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

前后端处理验证码kaptcha

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

前后端处理验证码kaptcha

方案
    前端在登录页面时,请求验证码的信息;后端可以利用UUID生成随机数key和验证码code存储在redis中,设置好倒计时间;后端再把随机数key和含验证码code的base64的图片传给前端;前端在登录接口时,把用户名/密码/key/验证码code一起传给后端;后端对前端传的key和code和redis中存储的进行比对,并把验证码失败或者成功结果传给前端;
代码实现 后端

kaptcha谷歌验证码工具依赖

 
 
     com.github.penggle
     kaptcha
     2.3.2
 

config文件配置图片验证码的生成规则;具体配置参数可查看此链接;

@Configuration
public class KaptchaConfig {

    @Bean
    DefaultKaptcha producer() {
        Properties properties = new Properties();
        properties.put("kaptcha.border", "no");
        properties.put("kaptcha.textproducer.font.color", "black");
        properties.put("kaptcha.textproducer.char.space", "4");
        properties.put("kaptcha.image.height", "40");
        properties.put("kaptcha.image.width", "120");
        properties.put("kaptcha.textproducer.font.size", "30");

        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);

        return defaultKaptcha;
    }
}

提供验证码的接口;别忘了在安全访问的配置中取消/captcha接口的token验证;

    @GetMapping("/captcha")
    public ResultJson captcha() throws IOException {

        String key = UUID.randomUUID().toString();
        String code = producer.createText();

        BufferedImage image = producer.createImage(code);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);

        base64Encoder encoder = new base64Encoder();
        String str = "data:image/jpeg;base64,";

        String base64Img = str + encoder.encode(outputStream.toByteArray());

        //存储key和code到redis中
        boolean flag = redisUtil.hset(Const.CAPTCHA_KEY, key, code, 120000); //时间是毫秒

		//传输base64验证码图片和token
        Map map = new HashMap<>();
        map.put("token", key);
        map.put("captchaImg", base64Img);

        return ResultJson.ok().data(map);
    }

CaptchaFilter 图片验证码校验过滤器

@Slf4j
@Component
public class CaptchaFilter extends OncePerRequestFilter {
   private final String loginUrl = "/login";
   @Autowired
   RedisUtil redisUtil;
   @Autowired
   LoginFailureHandler loginFailureHandler;
   @Override
   protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
         throws ServletException, IOException {
      String url = request.getRequestURI();
      if (loginUrl.equals(url) && request.getMethod().equals("POST")) {
         log.info("获取到login链接,正在校验验证码 -- " + url);
         try {
            validate(request);
         } catch (CaptchaException e) {
            log.info(e.getMessage());
            // 交给登录失败处理器处理
            loginFailureHandler.onAuthenticationFailure(request, response, e);
         }
      }
      filterChain.doFilter(request, response);
   }
   private void validate(HttpServletRequest request) {
      String code = request.getParameter("code");
      String token = request.getParameter("token");
      if (StringUtils.isBlank(code) || StringUtils.isBlank(token)) {
         throw new CaptchaException("验证码不能为空");
      }
      if(!code.equals(redisUtil.hget(Const.captcha_KEY, token))) {
         throw new CaptchaException("验证码不正确");
      }
      // 一次性使用
      redisUtil.hdel(Const.captcha_KEY, token);
   }
}
前端

请求/captcha接口

    getCaptcha() {
      this.$axios.get("/captcha").then((res) => {
        let data = res.data.data;
        this.loginForm.token = data.token;
        this.captchaImg = data.captchaImg;
      });

显示验证码,点击可切换验证码

            
              
              
            

请求登录接口方法

  data() {
    return {
      loginForm: {
        username: null,
        password: null,
        code: null,//验证码
        token: null,//验证码的token
      },
    };
  },
 methods: {
    loginSubmit(formName) {
      this.$refs[formName].validate((valid) => {
        //表单校验
        if (valid) {
          
          axios
            .post("/login", this.$qs.stringify(this.loginForm), {
              headers: { "Content-Type": "application/x-www-form-urlencoded" },
            })
            .then((response) => {
              console.log(response.data);
              var message = response.data.message;
              var success = response.data.success;
              var token = response.data.data.token;
              var refreshToken = response.data.data.refreshToken;
              console.log(message);

              var messageType = null;
              console.log("success的值:", success);
              console.log(typeof success);
              if (success === true) {
                messageType = "success";
              } else {
                messageType = "error";
                this.getCaptcha();//重新请求验证码接口
              }
              console.log(messageType);
              this.$message({
                //登录提示信息
                message: message,
                type: messageType, 
              });

              if (token) {
                //token有值
                localStorage.setItem("token", token); //将token存入本地
                localStorage.setItem("refreshToken", refreshToken); //将token存入本地
                this.$router.push({name:"Index"}); //跳转到首页
              }
            })
            .catch(function(error) {
              // 请求失败处理
              console.log(error);
            });
          console.log("login submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
}
参考

https://www.zhuawaba.com/post/19#%E7%94%9F%E6%88%90%E9%AA%8C%E8%AF%81%E7%A0%81

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777361.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号