laitimes

Java dynamically generates captchas

author:Starboy dreams

Operating environment:

IDEA:2021.2.4

Tomcat server: Tomcat 8.5.81

JDK:java1.8.0

Building a Java Web environment will not be explained in detail, because it is very basic!

Let's get to work!

Today we are going to create 2 classes [Generate Captcha class, Servlet class] and a JSP file that displays the QR code

To briefly explain first, this is a small feature [core] in one of my experiments

Here is my project structure directory: (FYI)

Java dynamically generates captchas

Our protagonist today is three of these files:

  1. The main function of the GenerateCodeServlet under the servlet package: to respond to our browser request and call the Java class ValidateCode to generate a verification code
  2. The ValidateCode class under the validate package, the main function: to generate our captcha image
  3. The ValidateCode .jsp under the web package displays our captcha

Start by creating our ValidateCode class

Code Reference:

package com.fly.code.validate;

import jdk.internal.util.xml.impl.Input;
import org.junit.Test;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @author: fly
 * @Date: 2023-03-24 8:52
 * @Description:
 *  1. 实现动态生成验证码字符串
 *  2. 验证码可使用大小写字母+数字的形式
 */
public class ValidateCode {

    public static int randomNumber(String str) {
        return (int) Math.floor(Math.random()*str.length());
    }

    /**
     * 动态生成验证码字符串 【数字+字母(大小写)】
     * @return 4位随机验证码
     */
    public static String generateCode(){
        // 从该字符串随机抽取 4 个字符
        String libs = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        StringBuilder buffer = new StringBuilder();
        for (int i = 0;i < 4;i++) {
            char ch = libs.charAt(randomNumber(libs));
            buffer.append(ch);
        }
        return String.valueOf(buffer);
    }

    /**
     * 生成图片
     */
    public static BufferedImage createImage(String code,String path,int imageWid,int imageHei,int imageType) {
        BufferedImage image = new BufferedImage(imageWid,imageHei,imageType);

        Graphics2D graph;

        graph =  image.createGraphics();
        // 设置背景色
        graph.setBackground(Color.WHITE);
        // 设置背景颜色填充范围
        graph.fillRect(0,0,imageWid,imageHei);
        // 设置画笔颜色
        graph.setColor(Color.BLACK);
        // 设置字体大小
        graph.setFont(new Font("微软雅黑", Font.PLAIN, 25));
        // graph.drawLine(0,16,imageWid,16);
        graph.drawString(code,imageWid/5,25);

        // 保存图片
        try {
            ImageIO.write(image,"JPG",new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return image;
    }

    /**
     * 保存图片
     */
    public static void save(String savePath,String filepath,HttpServletRequest request) {
        InputStream is = null;
        OutputStream os = null;

        byte[] buffer = new byte[1024];
        int len = 0;

        try {
            is = new FileInputStream(filepath);
            os = new FileOutputStream(savePath);

            while((len = is.read(buffer)) != -1) {
                os.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}           

Among them, the method of saving pictures (save) is not used Oh~

Next, create our GenerateCodeServlet class

Code:

package com.fly.code.servlet; /**
 * @author: fly
 * @Date: 2023-03-24 9:12
 * @Description: 返回验证码图片
 */

import com.fly.code.validate.ValidateCode;
import org.apache.tomcat.jni.Time;
import org.junit.Test;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;
import java.util.UUID;

@WebServlet(name = "GenerateCodeServlet", value = "/generateCodeServlet")
public class GenerateCodeServlet extends HttpServlet {

    private static final String BASE_URL = "D:\\学习2\\大三下\\物联网平台应用设计\\实验4";

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取随机验证码
        String code = ValidateCode.generateCode();
        // HttpSession对象存储验证码
        HttpSession session = request.getSession();
        session.setAttribute("code",code);
        // BufferedImage(一个带缓冲区图像类)将生成的验证码图片存到一个图像缓冲区
        String uuid = String.valueOf(UUID.randomUUID());
        uuid = uuid.replaceAll("-","");
        session.setAttribute("uuid",uuid);
        String path = "/validate-code/" + uuid + ".jpg";
        String realPath = request.getServletContext().getRealPath(path);
        // 创建二维码图片,并保存到 /validate-code 目录下
        ValidateCode.createImage(code,realPath,100,32,BufferedImage.TYPE_INT_RGB);
        try {
            // 等待图片生成完毕
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 重定向到登录页面
        response.sendRedirect("/test/ValidateCode.jsp");
    }
}
           

Finally, create the JSP file

Code:

<%@ page import="java.io.*" %><%--
  Created by IntelliJ IDEA.
  User: local-feng
  Date: 2023/3/24
  Time: 10:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>验证码图片显示</title>
</head>
<body>
    <%
        String uuid = (String) session.getAttribute("uuid");
        String path = "/validate-code/" + uuid + ".jpg";
        path = request.getContextPath() + path;
    %>
    <img src="<%=path%>" title="验证码" alt="验证码">
</body>
</html>           

Okay, run our Tomcat container!

Tomcat is configured as follows:

Java dynamically generates captchas

Visit our website: http://localhost:8023/test/generateCodeServlet

After waiting 5 seconds for the captcha image to be generated, we successfully see the captcha in the browser

Java dynamically generates captchas

We can also see the captcha image we generated in File Explorer:

Java dynamically generates captchas

Expand your knowledge:

With captcha, what can we do? Of course, the landing page!

Understand this dynamic generation of captcha, you can also make a landing page!

Maybe it's not me who generates the verification code online, because this method is too slow, and I need to wait for the generation time of the verification code image.

For example: like this! This is an experiment in our class, [of course, the interface is not carefully beautified]

Java dynamically generates captchas