手把手教你用Java实现一个简单的验证码功能

一、引言

大家好,今天我将带领大家一步步学习如何用Java实现验证码功能
验证码在网站和应用程序中起到了非常重要的作用,它可以有效防止恶意注册、登录和垃圾信息等,下面我们就开始吧!

二、验证码概述

简单来说:验证码是一种区分人类与机器人的安全测试,通过要求用户完成特定任务来防止自动化攻击和保障账户安全

三、实现步骤

验证码生成思路

生成随机字符----> 绘制字符到图片----> 添加干扰元素(如线条、噪点等)

那我们直接上代码吧
首先定义了一个CaptchaUtils 用来生成验证码,先定义一会备用

public class CaptchaUtils {

    // 验证码字符集
    private static final char[] CHAR_SET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
    // 图像宽度和高度
    private static final int WIDTH = 80;
    private static final int HEIGHT = 40;
    // 验证码字符个数
    private static final int LENGTH = 4;

    /**
     * 创建验证码图像并返回验证码上的文本
     *
     * @param request  HttpServletRequest, 用于获取会话
     * @param response HttpServletResponse, 用于输出图像到客户端
     * @return 返回生成的验证码文本
     */
    public static String createCaptchaImage(HttpServletRequest request, HttpServletResponse response) {
        // 在这里创建或获取会话
        HttpSession session = request.getSession();

        // 创建BufferedImage对象,作为图像缓冲区
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 获取Graphics2D对象,用于绘制图像
        Graphics2D g = image.createGraphics();

        // 设置背景色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        // 设置字体
        g.setFont(new Font("Arial", Font.BOLD, 20));

        // 生成随机验证码
        StringBuilder captcha = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < LENGTH; i++) {
            char randomChar = CHAR_SET[random.nextInt(CHAR_SET.length)];
            captcha.append(randomChar);
            // 设置字体颜色
            g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            g.drawString(String.valueOf(randomChar), 20 * i + 10, 30);
        }

        // 绘制干扰线
        for (int i = 0; i < 10; i++) {
            g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            g.drawLine(random.nextInt(WIDTH), random.nextInt(HEIGHT), random.nextInt(WIDTH), random.nextInt(HEIGHT));
        }

        // 释放Graphics2D对象
        g.dispose();

        // 设置响应头
        response.setContentType("image/jpeg");
        try {
            // 将图像输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());
            // 刷新输出流
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 将验证码文本保存到会话中,以便进行验证
        session.setAttribute("captchaText", captcha.toString());

        // 返回生成的验证码文本
        return captcha.toString();
    }
}

然后我们来定义CaptchaServlet 来处理请求,当CaptchaServlet被调用时候会执行 CaptchaUtils中的创建二维码的逻辑,进而将验证码信息保存到Session中以便后续验证

public class CaptchaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建验证码图片并返回图片上的文本
        String captchaText = CaptchaUtils.createCaptchaImage(request,response);
        // 将验证码文本保存到Session中
        HttpSession session = request.getSession();
        session.setAttribute("captcha", captchaText);
    }

}

我是在WebConfig中注册的,你可以用别的方式,用户访问/captcha路径时,CaptchaServlet将被调用

@Configuration
public class WebConfig {

    @Bean
    public ServletRegistrationBean<CaptchaServlet> CaptchaServlet() {
        return new ServletRegistrationBean<>(new CaptchaServlet(), "/captcha");
    }


}

前端代码如下

<el-form-item label="验证码" prop="captcha" width="120">
	<el-row>
		<el-col :span="18">
			<el-input
				id="captchaInput"
				type="text"
				v-model="userForm.captcha"
				placeholder="验证码">
			</el-input>
 		</el-col>
		<el-col :span="6">
			<el-image
				id="captchaImage"
				@click="refreshCaptcha"
				style="width: 80px;height: 40px"
				src="/captcha"
				fill="fill">
			</el-image>
		</el-col>
	</el-row>
</el-form-item>

下面是点击图片刷新验证码的逻辑对应上图中的 @click=“refreshCaptcha”
在url后加上new Date().getTime() 的目的是为了确保每次请求验证码时,浏览器不会使用缓存的图片,而是重新从服务器获取一个新的验证码图片

refreshCaptcha() {
            $.ajax({
                url: '/captcha',
                type: 'GET',
                contentType: 'application/x-www-form-urlencoded',
                processData: false,
                success: function (data) {
                    var captchaImage = document.getElementById('captchaImage');
                    captchaImage.src = '/captcha?' + new Date().getTime()
                }
            })
        },

那我应该怎么接收这个图像呢?
这是个好问题,我当时因为这个琢磨了好一会子,在开发者工具中能预览图像就是不知道怎么接收,大概如下,可以看的到生成的验证码图形
在这里插入图片描述
然后开开心心的点开响应,what???
在这里插入图片描述
然后发现,直接在img中的src中写上路径就可以了,可能也有别的方法,希望有大佬可以指点指点
那我就好奇这是为什么呢?
原因如下

HTTP请求:当浏览器解析到 <el-image src="/captcha"> 标签时,它会自动发送一个HTTP GET请求到指定的URL(在本例中是 /captcha)
URL映射:在Spring Boot应用中,我定义了一个CaptchaServlet 并将其映射到了 /captcha 路径,这意味着任何到 /captcha 的请求都会被 CaptchaServlet 的 service 方法处理
Servlet处理:当请求到达后端并被映射到 CaptchaServlet 时,CaptchaServlet 的逻辑会被执行,就是刚才咱们写的CaptchaUtils会生成一个验证码图片,并将其作为响应发送回客户端
响应处理:浏览器接收到来自后端的响应,这个响应包含验证码图片的二进制数据,然后,浏览器将这些数据渲染为图片,显示在 <el-image> 标签所在的位置

然后就没有然后了,到此一个简单的验证码功能我们已经实现了
那我们假如要验证该怎么验证呢,在我们上篇文章中loginServlet中有相关逻辑,有兴趣的可以去看一下,在这不再叙述
点击跳转上一篇文章

四、总结

通过本文的讲解,相信大家对Java实现一个简单的验证码功能已经有了一定的了解,还不快去动手试试!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值