【技术】纯Java编写算数验证码

纯Java编写算数验证码

工具类

工具类包含两个核心方法:
getCode(Integer width, Integer height):生成算数验证吗
getCode(Integer width, Integer height, Integer count, Integer size):生成普通验证码

public class Captcha {
    /**
     * 生成验证码图片
     *
     * @param width  图片宽度,默认:130
     * @param height 图片高度,默认:40
     * @param count  验证码字符个数,默认:4
     * @param size  验证码干扰麻点的个数,默认:150
     * @return Map<String, BufferedImage> 键:生成的验证码;值:图片缓冲对象
     * @throws Exception
     */
    public static Map<String, BufferedImage> getCode(Integer width, Integer height, Integer count, Integer size) {
        // 定义图片的宽高
        width = (width == null || width == 0) ? 130 : width;
        height = (height == null || height == 0) ? 40 : height;
        // 验证码的个数
        count = (count == null || count == 0) ? 4 : count;
        size = (size == null || size == 0) ? 150 : size;

        // 字符库
        char[] codes = {'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', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};

        // 图片缓冲区,定义宽高和颜色的编码
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 获取画板
        Graphics graphics = bi.getGraphics();

        // 设置颜色
        graphics.setColor(Color.WHITE);
        // 填充背景色
        graphics.fillRect(0, 0, width, height);

        // 从字符库中获取内容
        Random random = new Random();

        // 存储验证码
        StringBuffer sb = new StringBuffer();

        // 循环获取随机的字符
        for (int i = 1; i <= count; i++) {
            // 随机数,生成 0 - 字符库数量
            int index = random.nextInt(codes.length);
            // 从字符库中获取字符
            String code = codes[index] + "";
            sb.append(code);

            // 设置画笔颜色
            graphics.setColor(new Color(getRandomColor(), getRandomColor(), getRandomColor()));

            // 设置字体样式
            Font font = new Font("微软雅黑", Font.ITALIC, height / 2 + 5);
            graphics.setFont(font);

            // 把字符画到画布上
            graphics.drawString(code, width / (count + 2) * i, height / 2 + 5);
        }

        // 线条干扰项
        // 设置画笔颜色
        graphics.setColor(new Color(getRandomColor(), getRandomColor(), getRandomColor()));
        // 画线
        graphics.drawLine(10, 10, 120, 30);
        graphics.drawLine(10, 30, 120, 10);

        // 随机麻点干扰项
        for (int j = 0; j < size; j++) {
            // 设置画笔颜色
            graphics.setColor(Color.RED);

            int x = random.nextInt(width);
            int y = random.nextInt(height);
            // 画线
            graphics.drawLine(x, y, x, y);
        }

        Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
        map.put(sb.toString(), bi);

        return map;
    }

    /**
     * 生成表达式验证码
     * @param width  图片宽度,默认:130
     * @param height 图片高度,默认:40
     * @return Map<String, BufferedImage> 键:表达式的值;值:图片缓冲对象
     */
    public static Map<String, BufferedImage> getCode(Integer width, Integer height) {
        // 定义图片的宽高
        width = (width == null || width == 0) ? 130 : width;
        height = (height == null || height == 0) ? 40 : height;

        // 图片缓冲区,定义宽高和颜色的编码
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 获取画板
        Graphics graphics = bi.getGraphics();

        // 设置颜色
        graphics.setColor(Color.WHITE);
        // 填充背景色
        graphics.fillRect(0, 0, width, height);

        // 定义随机数对象
        Random random = new Random();
        // 获取10以内的随机值
        int i1 = random.nextInt(10);
        int i2 = random.nextInt(10);

        // 定义运算符数组
        char[] operators = {'+', '-', '*', '/'};
        // 根据数组获取随机下标
        int index =  random.nextInt(operators.length);
        // 根据下标获取运算符
        String operator = operators[index] + "";

        // 定义结果
        int result = 0;

        // 判定运算符
        switch (operator){
            case "+":
                result = i1 + i2;
                break;
            case "-":
                result = i1 - i2;
                break;
            case "*":
                result = i1 * i2;
                break;
            case "/":
                result = i1 / i2;
                break;
        }

        // 设置画笔颜色
        graphics.setColor(new Color(getRandomColor(), getRandomColor(), getRandomColor()));

        // 设置字体样式
        Font font = new Font("微软雅黑", Font.ITALIC, height / 2 + 5);
        graphics.setFont(font);

        // 构建表达式
        String expression = i1 + " " + operator + " " + i2 + " = " + " ?";
        // 把表达式画到画布上
        graphics.drawString(expression, width / 15, height / 2 + 5);

        // 存储结果
        Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
        map.put(result + "", bi);

        return map;
    }

    /**
     * 随机生成颜色代码,范围是0-255的rgb颜色
     *
     * @return
     */
    public static int getRandomColor() {
        return new Random().nextInt(255);
    }
}

测试类

测试类基于 Servlet 编写,也可以使用 SSM 框架和其他框架。

@WebServlet("/getCode")
public class GetCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 通过工具类获取验证码map,图片的宽高可以从前台页面获取
        Map<String, BufferedImage> code = Captcha.getCode(130, 40, 4, null);

        // 遍历map
        Iterator<String> iterator = code.keySet().iterator();

        if(iterator.hasNext()){
            // 获取key
            String key = iterator.next();
            // 把key存储到Session中便于登录时获取校验
            req.getSession().setAttribute("yzmCode", key);
            // 通过key获取字符缓冲对象,写入磁盘
            ImageIO.write(code.get(key), "JPEG", new FileOutputStream("D://yzmCode.jpg"));
            // 通过key获取字符缓冲对象,写入浏览器输出对象
            ImageIO.write(code.get(key), "JPEG", resp.getOutputStream());
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值