java-使用Graphics类绘制验证码

1,182 阅读2分钟

一、实现工具

  • 语言:java
  • 编辑器:IntelliJ IDEA 2019.3.3 x64

二、实现功能

  • 随机生成一组字符串 String randomString(int count)

  • 对图片进行噪点处理 void randompoint(BufferedImage img, Random rd)

  • 对图片进行划线处理 void line(Graphics g, Random rd)

  • 复制像素使图片信息模糊 void shear(Graphics g)

  • 校验码信息的传递 req.getSession().setAttribute("code",code);

三、实现代码

/**
  package org.example.project2.controller;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

@WebServlet("/captcha")
public class CaptcheController extends HttpServlet {
    private final int Width=100;
    private final int Height=80;
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BufferedImage img =new BufferedImage(Width,Height,BufferedImage.TYPE_INT_RGB);
        Graphics g=img.getGraphics();
        Random rd=new Random();
        g.fillRect(0,0,Width,Height);
        g.setFont(new Font("宋体",Font.BOLD,35));
        g.setColor(Color.black);
        String code=randomString(4);
        req.getSession().setAttribute("code",code);
        g.drawString(code,10,55);
        line(g,rd);
        shear(g);
        g.dispose();
        randompoint(img,rd);
        ServletOutputStream out =resp.getOutputStream();
        ImageIO.write(img,"JPEG",out);
        try{
            out.flush();
        }catch (Exception ex){}
        finally {
            out.close();
        }
    }

    /**
     * 通过制造噪点,使图片的信息变得混乱,让验证码不易被机器识别。
     * @param img 生成的图片
     * @param rd 随机生成的数值
     */
    private void randompoint(BufferedImage img, Random rd) {
        float zd = 0.05f;
        int area = (int) (zd * Width * Height);
        for (int i = 0; i < area; i++) {
            int x = rd.nextInt(Width);
            int y = rd.nextInt(Height);
            img.setRGB(x, y, 0);
        }
    }

    /**
     *通过划线将图片的信息进行部分掩盖,让验证码不易被机器识别。
     * @param g 绘制的图片
     * @param rd 随机生成的数字
     */
    private void line(Graphics g, Random rd){
        g.setColor(Color.red); //此处的setcolor是在drawString完成后实行,所以设置的是为线条的颜色。
        for (int i = 0; i < 20; i++) {
            int x = rd.nextInt(Width - 1);
            int y = rd.nextInt(Height - 1);
            int xl = rd.nextInt(6) + 1;
            int yl = rd.nextInt(12) + 1;
            g.drawLine(x, y, x+xl+40, y+yl+20);
        }
    }
    /**
     *通过复制像素,使图片变得模糊,让验证码不易被机器识别。
     * @param g 绘制的图片
     */
    private void shear(Graphics g) {
        Random r=new Random(1);
        for (int i = 0; i < Width; i++) {
            g.copyArea(0, i, Height, 1, r.nextInt(5), 0);
        }
    }




    /**
     * 随机生成一组字符串
     * @param count:生成的字符串中的字符个数
     * @return 生成的随机字符串信息
     */
    public String randomString(int count){
        StringBuilder builder=new StringBuilder();
        String source="abcdefghijklmnpqrstuvwxy0123456789";
        Random rd=new Random();
        for (int i=0;i<count;i++) {
            int pos = rd.nextInt(source.length());
            String s = source.substring(pos, pos + 1);
            builder.append(s);
        }
        return builder.toString();
    }
}


四、结果截图

五、部分可修改的值介绍

  • 更改randomString(int count)下的source字符串取值进行校验码取值范围修改。
  • 更改shear(Graphics g)下的 r.nextInt(5)进行复制像素修改,数值越大,图片越散碎反之数值越小越整齐。