Java Web验证码功能

本文详细介绍了如何在JavaWeb应用中使用BufferedImage类和Graphics对象实现手动生成验证码的功能,包括创建工具类、定制画板、绘制数字和干扰线,最后返回字节数组对象供前端展示。
摘要由CSDN通过智能技术生成

Java Web验证码功能

1 明确需求

  • 验证码最常用的是一个图片类型的验证码,由后端进行产生并且发送到前端页面显示。
  • 验证码的生成原理简单来说就是在一张画板上面,画上数字或字母,以及点缀一些干扰信息。
  • 这里只介绍手动生成的简单方案,明白原理即可。

2 BufferedImage类介绍

import java.awt.image.BufferedImage继承java.awt.Image类,BufferedImage是一个带缓冲区的图像类,可以将图片加载到内存的一片连续区域中,这样可以非常方便对加载的图像进行操作,包括图像剪切旋转缩放、图像绘制、像素级别的处理、灵活的图片格式等。

BufferedImage是没有读取功能,只能通过ImageIO类进行IO操作:

ImageIO.read()  // 返回BufferedImage类型
ImageIO.write()  //写到输出流,或者文件对象

3 实现

3.1 创建工具类

创建验证码工具类,这个工具可以传入绘制的图像的宽和高,以及所需绘制数字的位数

public class CaptchaUtil {
    public static byte[] getCaptcha(int width, int height, int num) {
    }
}

3.2 创建画板

//创建一个BufferedImage对象
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);

// 创建Graphics对象,用于绘制图像  真正提供绘图功能的是Graphics对象
Graphics graphics = bufferedImage.createGraphics();

3.3 定制画笔

先选择自己需要的画笔,再在画板中绘制

//设置画笔颜色
graphics.setColor(Color.WHITE);
//使用画笔填充背景颜色
graphics.fillRect(0, 0, width, height);
//设置字体
graphics.setFont(new Font("Times New Roman", Font.PLAIN, 20));

3.4 画数字

//生成随机码
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < num; i++) {
    String code = String.valueOf(random.nextInt(10));
    sb.append(code);
    // 设置随机颜色 为了对不同的数字实现随机颜色的效果
    graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
    // 绘制验证码
    graphics.drawString(code, 20 * i + 10, 25);
}

3.5 绘制干扰线

// 绘制干扰线
for (int i = 0; i < 6; i++) {
    //设置画笔随机颜色
    graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
    //生成直线的坐标,两点确定一条直线
    int x1 = random.nextInt(width);
    int y1 = random.nextInt(height);
    int x2 = random.nextInt(width);
    int y2 = random.nextInt(height);
    graphics.drawLine(x1, y1, x2, y2);
}

3.6 返回字节数组对象

// 释放Graphics对象
graphics.dispose();

//输出图片到输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "JPEG", outputStream);```java

// 获取图片的字节数组并返回
return outputStream.toByteArray();

4 返回字节流

@RequestMapping("/user/getCaptcha")
public ResponseEntity<byte[]> getCaptcha(HttpServletResponse response) throws IOException {
    byte[] captcha = CaptchaUtil.getCaptcha(100, 30, 4);

    // 设置响应头
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.IMAGE_JPEG);
    httpHeaders.setContentLength(captcha.length);

    return new ResponseEntity<>(captcha, httpHeaders, HttpStatus.OK);
}

5 测试效果

element-plus实现

<el-form-item label="验证码">
	<el-input v-model="ruleForm.code" type="text" autocomplete="off" style="width: 70%" />
	<el-image style="width: 30%; height: 32px; border: 1px solid #8ca2ab;" :src="captchaUrl" fit="fill"
		@click="getCodeImg()" />
</el-form-item>

在这里插入图片描述

6 所有代码

6.1 CaptchaUtil

package com.song.util;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * 生成captcha的工具类
 */
public class CaptchaUtil {

    public static byte[] getCaptcha(int width, int height, int num) throws IOException {
        //创建一个BufferedImage对象
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);

        // 创建Graphics对象,用于绘制图像
        Graphics graphics = bufferedImage.createGraphics();

        //设置画笔颜色
        graphics.setColor(Color.WHITE);
        //使用画笔填充背景颜色
        graphics.fillRect(0, 0, width, height);
        //设置字体
        graphics.setFont(new Font("Times New Roman", Font.PLAIN, 20));

        //生成随机码
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < num; i++) {
            String code = String.valueOf(random.nextInt(10)); // 10以内的数字
            sb.append(code);
            // 设置随机颜色
            graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            // 绘制验证码
            graphics.drawString(code, 20 * i + 10, 25);
        }

        String captcha = sb.toString();
        // 打印验证码
        System.out.println("验证码:" + captcha);

        // 绘制干扰线
        for (int i = 0; i < 6; i++) {
            //设置画笔随机颜色
            graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            //生成直线的坐标,两点确定一条直线
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            graphics.drawLine(x1, y1, x2, y2);
        }

        // 释放Graphics对象
        graphics.dispose();

        //输出图片到输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "JPEG", outputStream);

        // 获取图片的字节数组
        return outputStream.toByteArray();

    }
}

6.2 Controller代码

    @RequestMapping("/user/getCaptcha")
    public ResponseEntity<byte[]> getCaptcha(HttpServletResponse response) throws IOException {
        byte[] captcha = CaptchaUtil.getCaptcha(100, 30, 4);

        // 设置响应头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.IMAGE_JPEG);
        httpHeaders.setContentLength(captcha.length);

        return new ResponseEntity<>(captcha, httpHeaders, HttpStatus.OK);
    }

6.3 前端代码

可以在浏览器直接输入请求地址查看http://127.0.0.1:8081/user/getCaptcha ,换成自己的地址。

<el-form-item label="验证码">
	<el-input v-model="ruleForm.code" type="text" autocomplete="off" style="width: 70%" />
	<el-image style="width: 30%; height: 32px; border: 1px solid #8ca2ab;" :src="captchaUrl" fit="fill"
		@click="getCodeImg()" />
</el-form-item>
//验证码
var captchaUrl = ref(store.baseUrl + "/user/getCaptcha")
const getCodeImg = () => {
	//Date.now()防止浏览器缓存而不发送请求
	captchaUrl.value = store.baseUrl + "/user/getCaptcha?data=" + Date.now()
}
  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不当菜虚困

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值