文字图片验证码源码

一. 验证码前篇

概述

  • 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。

二. 关键代码

  • 1.显示随机字母或数字的验证码
package com.example.demo.controller;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Random;

public class VerifyCodeUtils {
  private final static int width = 800;  //验证码宽度
  private final static int height = 300;  //验证码高度
  private final static int codeCount = 4;  //验证码字符个数
  private final static int fontHeight = 150;  //字体高度
  private static String verifyVariable;

  public static String getVerifyVariable() {
    return verifyVariable;
  }

  /**
   * 获取验证码图片
   */
  public static byte[] getVerifyImg() throws IOException {
    //定义装验证码的String

    StringBuilder verifyVariableBuilder = new StringBuilder();

    Random random = new Random();

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics graphic = image.getGraphics();

    graphic.setColor(Color.getColor("F8F8F8"));
    graphic.fillRect(0, 0, width, height);

    Color[] colors = new Color[]{Color.BLUE, Color.GRAY, Color.GREEN, Color.RED, Color.BLACK, Color.ORANGE,
      Color.CYAN};
    // 在 "画板"上生成干扰线条 ( 50 是线条个数)
    for (int i = 0; i < (int) (300 * Math.random() + 200); i++) {
      graphic.setColor(colors[random.nextInt(colors.length)]);
      final int x = random.nextInt(width);
      final int y = random.nextInt(height);
      final int w = random.nextInt(20);
      final int h = random.nextInt(20);
      final int signA = random.nextBoolean() ? 1 : -1;
      final int signB = random.nextBoolean() ? 1 : -1;
      int[] data = new int[]{x, y, 20, 0, -10};
      graphic.drawLine(data[(int) (Math.random() * 5)], data[(int) (Math.random() * 5)], x + w * signA, y + h * signB);
    }


    String str = "0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z、a、b、c、d、e、f、g、h、i、j、k、l、m、n、o、p、q、r、s、t、u、v、w、x、y、z";
    String[] split = str.split("、");
    // 在 "画板"上绘制字母
    graphic.setFont(new Font("Comic Sans MS", Font.BOLD, fontHeight));
    for (int i = 0; i < codeCount; i++) {
      String s = split[(int) (Math.random() * split.length)];
      System.out.println(s);
      //将四位验证码字母组合为String
      verifyVariableBuilder.append(s);
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString(s, i * (width / 4), height - (height / 3));
    }
    graphic.dispose();

    verifyVariable = verifyVariableBuilder.toString();

    //打印显示
    System.out.println("验证码答案:" + verifyVariable);


    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(image, "png", os);
    return os.toByteArray();
  }

  public static void main(String[] args) {
    try {
      byte[] verifyImg = VerifyCodeUtils.getVerifyImg();
      FileImageOutputStream imageOutput = new FileImageOutputStream(new File("D://image3.jpg"));
      imageOutput.write(verifyImg, 0, verifyImg.length);//将byte写入硬盘
      imageOutput.close();
    } catch (Exception e) {
    }
  }
}

 效果图:

  • 2.显示计算公式的验证码
package com.example.demo.controller;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.*;

public class VerifyCodeUtilOfMath {
  private final static int width = 800;  //验证码宽度
  private final static int height = 300;  //验证码高度
  private final static int codeCount = 5;  //验证码字符个数
  private final static int fontHeight = 150;  //字体高度
  private static String verifyVariable;
  private static int firstNum;        //第一位数字

  public static String getVerifyVariable() {
    return verifyVariable;
  }

  /**
   * 获取验证码图片
   */
  public static byte[] getVerifyImg() throws IOException {
    //定义装验证码的String

    StringBuilder verifyVariableBuilder = new StringBuilder();

    Random random = new Random();

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics graphic = image.getGraphics();

    graphic.setColor(Color.getColor("F8F8F8"));
    graphic.fillRect(0, 0, width, height);

    Color[] colors = new Color[]{Color.BLUE, Color.GRAY, Color.GREEN, Color.RED, Color.BLACK, Color.ORANGE,
      Color.CYAN};
    // 在 "画板"上生成干扰线条 ( 50 是线条个数)
    for (int i = 0; i < (int) (300 * Math.random() + 200); i++) {
      graphic.setColor(colors[random.nextInt(colors.length)]);
      final int x = random.nextInt(width);
      final int y = random.nextInt(height);
      final int w = random.nextInt(20);
      final int h = random.nextInt(20);
      final int signA = random.nextBoolean() ? 1 : -1;
      final int signB = random.nextBoolean() ? 1 : -1;
      int[] data = new int[]{x, y, 20, 0, -10};
      graphic.drawLine(data[(int) (Math.random() * 5)], data[(int) (Math.random() * 5)], x + w * signA, y + h * signB);
    }

    //定义运算符号
    List list = new ArrayList();
    Collections.addAll(list, "+", "-", "X", "÷");
    //Collections.addAll(list, "÷");
    String yunsuan = (String) list.get((int) (Math.random() * list.size()));
    // 在 "画板"上绘制字母
    graphic.setFont(new Font("Comic Sans MS", Font.BOLD, fontHeight));

    if (yunsuan.equals("÷")) {
      Map<Integer, Integer> map = new HashMap<Integer, Integer>();
      map.put(3, 1);
      map.put(2, 1);
      map.put(6, 3);
      map.put(4, 4);
      map.put(8, 4);
      map.put(10, 2);
      map.put(9, 3);
      map.put(12, 2);
      map.put(15, 5);
      map.put(14, 2);
      map.put(16, 8);
      map.put(18, 6);
      map.put(20, 4);
      map.put(21, 7);
      List<Integer> list1 = new ArrayList<Integer>();
      Collections.addAll(list1, 3, 2, 6, 4, 8, 10, 9, 12, 15, 14, 16, 18, 20, 21);
      int numRandom = getNumRandom(0, 9);
      int key = list1.get(numRandom);
      Integer value = map.get(key);

      //将四位验证码字母组合为String
      verifyVariableBuilder.append(key + "÷" + value);      //添加进答案
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString(key + "", 0 * (width / 6), height - (height / (9 / 2)));
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString("÷", 1 * (width / 6), height - (height / (9 / 2)));
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString(value + "", 2 * (width / 6), height - (height / (9 / 2)));
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString("=", 3 * (width / 6), height - (height / (9 / 2)));
      graphic.setColor(colors[random.nextInt(colors.length)]);
      graphic.drawString("?", 4 * (width / 6), height - (height / (9 / 2)));
    } else {
      // 加减乘
      for (int i = 0; i < codeCount; i++) {
        if (i == 1) {         //运算符号
          verifyVariableBuilder.append(yunsuan);      //添加进答案
          graphic.setColor(colors[random.nextInt(colors.length)]);
          graphic.drawString(yunsuan + "", i * (width / 6), height - (height / (9 / 2)));
        }
        if (i == 3) {
          graphic.setColor(colors[random.nextInt(colors.length)]);// = 号
          graphic.drawString("=", i * (width / 6), height - (height / (9 / 2)));
        }
        if (i == 4) {
          graphic.setColor(colors[random.nextInt(colors.length)]);   // ? 号
          graphic.drawString("?", i * (width / 6), height - (height / (9 / 2)));
        }
        if (i == 0 || i == 2) {
          if (yunsuan.equals("-")) {
            if (i == 0) {
              setNumVerify(verifyVariableBuilder, graphic, i, 5, 15, colors[random.nextInt(colors.length)]);
            } else {
              setNumVerify(verifyVariableBuilder, graphic, i, 0, firstNum, colors[random.nextInt(colors.length)]);
            }
          } else {
            setNumVerify(verifyVariableBuilder, graphic, i, 1, 9, colors[random.nextInt(colors.length)]);
          }
        }
      }
    }
    graphic.dispose();
    verifyVariable = verifyVariableBuilder.toString();
    //打印显示
    System.out.println("验证码答案:" + verifyVariable);
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(image, "png", os);
    return os.toByteArray();
  }

  private static void setNumVerify(StringBuilder verifyVariableBuilder, Graphics graphic, int i, int i2, int i3, Color color) {
    int s = getNumRandom(i2, i3);
    System.out.println(s);
    //将四位验证码字母组合为String
    verifyVariableBuilder.append(s);      //添加进答案
    graphic.setColor(color);
    graphic.drawString(s + "", i * (width / 6), height - (height / (9 / 2)));
    if (i == 0) {
      firstNum = s;
    }
  }

  private static int getNumRandom(int min, int max) {
    return (int) (Math.random() * (max + 1 - min) + min);   //产生10-20任意随机整数
  }

  public static void main(String[] args) throws IOException {
    byte[] verifyImg = VerifyCodeUtilOfMath.getVerifyImg();
    FileImageOutputStream imageOutput = new FileImageOutputStream(new File("D:\\验证码.png"));//打开输入流
    imageOutput.write(verifyImg, 0, verifyImg.length);//将byte写入硬盘
    String verifyVariable = VerifyCodeUtilOfMath.getVerifyVariable();
    System.out.println("我是答案:" + verifyVariable);
    int verifyNum = 0;
    if (verifyVariable.contains("÷")) {
      String[] split = verifyVariable.split("÷");
      verifyNum = Integer.valueOf(split[0]) / Integer.valueOf(split[1]);
    }
    if (verifyVariable.contains("+")) {
      String[] split = verifyVariable.split("\\+");
      verifyNum = Integer.valueOf(split[0]) + Integer.valueOf(split[1]);
    }
    if (verifyVariable.contains("-")) {
      String[] split = verifyVariable.split("-");
      verifyNum = Integer.valueOf(split[0]) - Integer.valueOf(split[1]);
    }
    if (verifyVariable.contains("X")) {
      String[] split = verifyVariable.split("X");
      verifyNum = Integer.valueOf(split[0]) * Integer.valueOf(split[1]);
    }

    System.out.println("运算答案为:" + verifyNum);
    imageOutput.close();
  }
}

效果图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值