JAVA点击图片中的文字验证码简单实现

前端显示效果

1、图片生成工具类实现


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;

/**
 * 绘制验证码
 */
public class DrawCaptchaUtil {

    /**
     * 画布宽度
     */
    private static int canvasWidth = 300;

    /**
     * 画布高度
     */
    private static int canvasHeight = 150;


    /**
     * 图片宽度
     */
    private static int imgWidth = 300;

    /**
     * 图片高度
     */
    private static int imgHeight = 150;

    /**
     * 图中字体数量
     */
    private static int charNumber = 5;

    /**
     * 字体大小
     */
    private static int fontSize = 18;
    /**
     * 字体图片宽度
     */
    private static int charImgWidth = 20;
    /**
     * 字体图片高度
     */
    private static int charImgHeight = 25;



    /**
     * 绘制验证码图片
     * @param checkCode
     * @param bkDirPath
     * @return
     * @throws IOException
     */
    public static BufferedImage drawImg(LinkedHashMap<String, AnchorPoint> checkCode,String bkDirPath) throws IOException {

        BufferedImage imgCanvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_BGR);
        Graphics graphics = imgCanvas.getGraphics();


        //绘制图形
//        graphics.setColor(new Color(0,0,0,0));
        graphics.fillRect(0,0,imgWidth,imgHeight);

        File bkPath = randomBackGroundImage(bkDirPath);

        BufferedImage read = ImageIO.read(Files.newInputStream(Paths.get(bkPath.getAbsolutePath())));
        graphics.drawImage(read,0,0,null,null);
        //绘制字体
//        graphics.setColor(getRandomColor());
        //随机在图片中生成5个绘制点每个绘制点半径能不能重叠
        Set<AnchorPoint> point = new HashSet<>();

        addPoint(point);
        Object[] pointArr = point.toArray();
        List<String> charList = new ArrayList<>();
        for (int i = 0; i < charNumber; i++) {
            AnchorPoint p = (AnchorPoint)pointArr[i];
            graphics.drawImage(getCharImg(getRandomColor(),charList),p.getX(),p.getY(),null,null);

        }
        //随机获取3个字符串作为校验对象
        Object[] charArr = charList.toArray();
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            int num = random.nextInt(pointArr.length-i);
            String key = (String) charArr[num];
            AnchorPoint value = (AnchorPoint) pointArr[num];
            checkCode.put(key,value);
            //置换位置
            Object a = pointArr[num];
            pointArr[num] = pointArr[pointArr.length - 1 - i];
            pointArr[pointArr.length - 1 - i] = a;

            a = charArr[num];
            charArr[num] = charArr[charArr.length - 1 -  i];
            charArr[charArr.length - 1 - i] = a;
        }

        return imgCanvas;
    }

    /**
     * 在指定目录下随机获取背景图片
     * @param dir
     * @return
     */
    private static File randomBackGroundImage(String dir){
        File file = new File(dir);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            Random random = new Random();
            int i = random.nextInt(files.length);
            return files[i];
        }else{
            return file;
        }
    }

    /**
     * 添加坐标点
     * @param point
     */
    private static void addPoint(Set<AnchorPoint> point){
        Random random = new Random();
        //避免因为坐标点过于特殊导致无法获取下一个坐标点进入死循环,到100置空重新获取
        int clearNumber = 0;
        //生成前2个点坐标
        while (point.size() < 2){

            //添加X坐标点
            point.add(new AnchorPoint(random.nextInt(canvasWidth/3),random.nextInt(canvasHeight-charImgWidth)));
            if(clearNumber == 100){
                point.clear();
                clearNumber = 0;
            }
            clearNumber++;

        }
        clearNumber = 0;
        //生成后3个点坐标
        while (point.size() < charNumber){
            //添加X坐标点
            point.add(new AnchorPoint(random.nextInt(canvasWidth-charImgWidth),random.nextInt(canvasHeight-charImgHeight)));
            if(clearNumber == 100){
                point.clear();
                clearNumber = 0;
                addPoint(point);
                break;
            }
            clearNumber++;
        }




    }

    /**
     * 获取文字图片
     * @param fontColor
     * @param charList
     * @return
     * @throws UnsupportedEncodingException
     */
    private static BufferedImage getCharImg(Color fontColor, List<String> charList) throws UnsupportedEncodingException {
        BufferedImage fillRect = new BufferedImage(charImgWidth, charImgHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = fillRect.createGraphics();
        g.setColor(new Color(0,0,0,0));
        g.fillRect(0,0,charImgWidth,charImgHeight);
        g.setColor(fontColor);
        Font font = new Font("微软雅黑", Font.BOLD, fontSize);
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.rotate(Math.toRadians(30),0,0);
        font.deriveFont(affineTransform);
        g.setFont(font);
        String charStr = getChineseCharacters();
        charList.add(charStr);
        g.drawString(charStr,0,charImgHeight-5);
        g.dispose();
        return fillRect;
    }

    /**
     * 随机获取颜色
     * @return
     */
    private static Color getRandomColor(){
        Random random = new Random();
        return new Color(
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255));

    }

    /**
     * 随机获取中文字
     * @return
     * @throws UnsupportedEncodingException
     */
    private static String getChineseCharacters() throws UnsupportedEncodingException {
        Integer hightPos, lowPos; // 定义高低位
        Random random = new Random();
        hightPos = (176 + Math.abs(random.nextInt(39)));
        lowPos = (161 + Math.abs(random.nextInt(93)));
        byte[] bytes = new byte[2];
        bytes[0] = hightPos.byteValue();
        bytes[1] =lowPos.byteValue();
        return new String(bytes,"GBK");

    }




}

2、验证码实体类




import java.io.Serializable;

public class AnchorPoint implements Serializable {

    private static final long serialVersionUID = 2L;


    /**
     * 保持charImgWidth的最大值+1
     */
    private Integer x_iv = 26;
    /**
     * 保持charImgHeight的最大值+1
     */
    private Integer y_iv = 21;

    private Integer x;
    private Integer y;

    public AnchorPoint(){
        this.x = 0;
        this.y = 0;
    }


    public AnchorPoint(Integer x, Integer y){
        this.x = x;
        this.y = y;
    }

    public Integer getX() {
        return x;
    }


    public Integer getY() {
        return y;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public void setY(Integer y) {
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AnchorPoint that = (AnchorPoint) o;

        //当X位置小于偏移量进行判段Y轴的偏移量
        if(this.x+this.x_iv > that.getX() || this.x - this.x_iv < that.getX()){
            //当Y轴的偏移量符合安全距离 判断锚点有效
            if(this.y+this.y_iv < that.getY() || this.y-this.y_iv > that.getY()){
                return false;
            }
        }else{
            //两个对象的X点保持在偏移量之外无需比较Y轴位置,判定锚点有效
            return false;
        }


        return true;

    }

    @Override
    public int hashCode() {
        return 1;
    }

    @Override
    public String toString() {
        return "AnchorPoint{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java实现图形验证码的步骤如下: 1. 生成随机字符串:可以使用Java内置的随机数生成器或者第三方库生成随机字符串,例如Apache Commons Lang的RandomStringUtils。 2. 生成验证码图片:可以使用Java内置的图形处理库或者第三方库生成图片。具体实现方法可以参考Java官方文档或者第三方库的文档。 3. 将随机字符串存储到Session:在生成验证码图片的同时,将生成的随机字符串存储到Session,以便后续验证用户输入的验证码是否正确。 4. 输出验证码图片:将生成的验证码图片输出到前端页面,让用户进行输入验证。 5. 验证用户输入的验证码:当用户提交表单时,从Session取出生成的随机字符串,与用户输入的验证码进行比较,以验证用户输入的验证码是否正确。 示例代码如下: ```java // 生成随机字符串 String randomStr = RandomStringUtils.randomAlphanumeric(6); // 将随机字符串存储到Session request.getSession().setAttribute("captcha", randomStr); // 生成验证码图片 BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 100, 30); g.setColor(Color.BLACK); g.setFont(new Font("Arial", Font.BOLD, 20)); g.drawString(randomStr, 10, 20); g.dispose(); // 输出验证码图片 response.setContentType("image/jpeg"); OutputStream out = response.getOutputStream(); ImageIO.write(image, "jpeg", out); out.close(); // 验证用户输入的验证码 String captcha = (String) request.getSession().getAttribute("captcha"); if (captcha != null && captcha.equalsIgnoreCase(userInput)) { // 验证码正确 } else { // 验证码错误 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值