当前位置 博文首页 > 文章内容

    javaWeb如何实现随机图片验证码详解

    作者:shunshunshun18 栏目:未分类 时间:2021-03-28 14:45:41

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    实现步骤

    1:Java后台生成一张随机数字/字母/汉字验证码的图片。

    2:存入redis或者session。

    3:用户输入验证码跟redis取出数据做比对。

    图片生成工具类

    public class RandomValidateCodeUtil {
    
    
     public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的key
     private String randString = "0123456789";//随机产生只有数字的字符串 private String
     //private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串
     //private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串
     private int width = 95;// 图片宽
     private int height = 25;// 图片高
     private int lineSize = 40;// 干扰线数量
     private int stringNum = 4;// 随机产生字符数量
    
     private static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil.class);
    
     private Random random = new Random();
    
     /**
      * 获得字体
      */
     private Font getFont() {
      return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
     }
    
     /**
      * 获得颜色
      */
     private Color getRandColor(int fc, int bc) {
      if (fc > 255) {
       fc = 255;
      }
      if (bc > 255) {
       bc = 255;
      }
      int r = fc + random.nextInt(bc - fc - 16);
      int g = fc + random.nextInt(bc - fc - 14);
      int b = fc + random.nextInt(bc - fc - 18);
      return new Color(r, g, b);
     }
    
     /**
      * 生成随机图片
      */
     public String getRandcode(HttpServletRequest request, HttpServletResponse response) {
      HttpSession session = request.getSession();
      // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
      BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
      Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
      g.fillRect(0, 0, width, height);//图片大小
      g.setFont(new Font("Default", Font.ROMAN_BASELINE, 18));//字体大小
      g.setColor(getRandColor(110, 133));//字体颜色
      // 绘制干扰线
      for (int i = 0; i <= lineSize; i++) {
       drowLine(g);
      }
      // 绘制随机字符
      String randomString = "";
      for (int i = 1; i <= stringNum; i++) {
       randomString = drowString(g, randomString, i);
      }
      logger.info(randomString);
      g.dispose();
      try {
       // 将内存中的图片通过流动形式输出到客户端
       ImageIO.write(image, "JPEG", response.getOutputStream());
      } catch (Exception e) {
       logger.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);
      }
      return randomString;
     }
    
     /**
      * 绘制字符串
      */
     private String drowString(Graphics g, String randomString, int i) {
      g.setFont(getFont());
      g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
        .nextInt(121)));
      String rand = String.valueOf(getRandomString(random.nextInt(randString
        .length())));
      randomString += rand;
      g.translate(random.nextInt(3), random.nextInt(3));
      g.drawString(rand, 13 * i, 16);
      return randomString;
     }
    
     /**
      * 绘制干扰线
      */
     private void drowLine(Graphics g) {
      int x = random.nextInt(width);
      int y = random.nextInt(height);
      int xl = random.nextInt(13);
      int yl = random.nextInt(15);
      g.drawLine(x, y, x + xl, y + yl);
     }
    
     /**
      * 获取随机的字符
      */
     public String getRandomString(int num) {
      return String.valueOf(randString.charAt(num));
     }
    }
    

    使用工具类生成

     @GetMapping(value = "/getVerify")
     @ApiOperation("生成图片验证码")
     public void getVerify(HttpServletRequest request, HttpServletResponse response) {
      try {
       //设置相应类型,告诉浏览器输出的内容为图片
       response.setContentType("image/jpeg");
       //设置响应头信息,告诉浏览器不要缓存此内容
       response.setHeader("Pragma", "No-cache");
       response.setHeader("Cache-Control", "no-cache");
       response.setDateHeader("Expire", 0);
       RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil();
       //输出验证码图片方法
       String randcode = randomValidateCode.getRandcode(request, response);
       
       // 将随机生成的字符串放在redis中
       redisUtil.save("random", randcode);
       
       // 将生成的随机字符串保存到session中
       // HttpSession session = request.getSession();
       // session.removeAttribute(RANDOMCODEKEY);
       // session.setAttribute(RANDOMCODEKEY, randomString);
    
      } catch (Exception e) {
       log.error("获取验证码失败>>>> ", e);
      }
     }
    

    当有请求进来时

    1:告诉浏览器如何接收图片。

    2:使用工具类生成图片 。

    3:将验证码存入redis或者seesion。

    4:调用成功图片已流给浏览器

    获得图片:

    校验图形验证码

    @PostMapping("/checkVerify")
      @ApiOperation("校验图形验证码")
      public String checkValidateCode(String verify) {
        // 校验验证码
        try {
          // 从redis中获取验证码
          String random = (String) redisUtil.findKey("random");
    
          // 从ression中获取验证码
          HttpSession session = request.getSession();
          String random = session.getAttribute("random");
    
          log.info("获取的随机数 random = {}", random);
          if (org.springframework.util.StringUtils.isEmpty(verify)) {
            return "没有输入验证码";
          }
          if (verify.equals(random)) {
            redisUtil.delKey("random");
          } else {
            return "验证码错误";
          }
        } catch (Exception e) {
          log.error("验证码校验失败", e);
          return "服务器异常";
        }
        return "成功";
      }
    

    验证:从redis或者seesion取出存入的验证码与用户输入的比对,相同验证成功,反之验证失败。

    总结