Java essay: using java to dynamically generate random verification code pictures

Keywords: Java JSP Javascript Session

Although java's graphics processing has always been a weak point, it does not prevent us from making some small things, such as our most common captcha image.

Small knowledge points used:

  1. A little awt knowledge is used, but it's very simple.
  2. Basic image io output, which belongs to basic knowledge.
  3. OutputStream,ImageIO,Random,BufferedImage

Here is the code to generate the verification code picture:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;

public class VerifyCode
{
  private int w = 70;
  private int h = 35;
  private Random r = new Random();
  
  private String[] fontNames = { "Song style", "Chinese script", "Blackbody", "Microsoft YaHei", "Regular script_GB2312" };
  
  private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
  
  private Color bgColor = new Color(255, 255, 255);
  private String text;
  
  public VerifyCode() {}
  
  private Color randomColor() {
    int red = r.nextInt(150);
    int green = r.nextInt(150);
    int blue = r.nextInt(150);
    return new Color(red, green, blue);
  }
  
  private Font randomFont()
  {
    int index = r.nextInt(fontNames.length);
    String fontName = fontNames[index];
    int style = r.nextInt(4);
    int size = r.nextInt(5) + 24;
    return new Font(fontName, style, size);
  }
  
  private void drawLine(BufferedImage image)
  {
    int num = 3;
    Graphics2D g2 = (Graphics2D)image.getGraphics();
    for (int i = 0; i < num; i++) {
      int x1 = r.nextInt(w);
      int y1 = r.nextInt(h);
      int x2 = r.nextInt(w);
      int y2 = r.nextInt(h);
      g2.setStroke(new BasicStroke(1.5F));
      g2.setColor(Color.BLUE);
      g2.drawLine(x1, y1, x2, y2);
    }
  }
  
  private char randomChar()
  {
    int index = r.nextInt(codes.length());
    return codes.charAt(index);
  }
  
  private BufferedImage createImage()
  {
    BufferedImage image = new BufferedImage(w, h, 1);
    Graphics2D g2 = (Graphics2D)image.getGraphics();
    g2.setColor(bgColor);
    g2.fillRect(0, 0, w, h);
    return image;
  }
  
  public BufferedImage getImage()
  {
    BufferedImage image = createImage();
    Graphics2D g2 = (Graphics2D)image.getGraphics();
    StringBuilder sb = new StringBuilder();
    
    for (int i = 0; i < 4; i++) {
      String s = randomChar() + "";
      sb.append(s);
      float x = i * 1.0F * w / 4.0F;
      g2.setFont(randomFont());
      g2.setColor(randomColor());
      g2.drawString(s, x, h - 5);
    }
    text = sb.toString();
    drawLine(image);
    return image;
  }
  
  public String getText()
  {
    return text;
  }
  
  public static void output(BufferedImage image, OutputStream out)
    throws IOException
  {
    ImageIO.write(image, "JPEG", out);
  }
  

}

Here is an example of a login application scenario:

  • First, we create a simple login interface:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login page</title>
<link rel="icon" href="image/icon1.png" />
<script type="text/javascript">
		function _change(){
			//Get img element
			var ele = document.getElementById("vCode");
			ele.src= "<c:url value='/VerifyCodeServlet'/>?xxx=" + new Date().getTime();
		}
	</script>
</head>
<body>
	<h1>Sign in</h1>
	<p style="color: red; font-weight: 900">${msg }</p>
	<form action="<c:url value="/LoginServlet"/>" method="post">
		User name:<input type="text" name="username" value="${user.username }"/><br />
		dense&nbsp;&nbsp;&nbsp;&nbsp;Code:<input type="password" name="password" value="${user.password }"/><br />
		Verification Code:<input type="text" name="verifyCode" size="3"/>
		<img id="vCode" src="<c:url value='/VerifyCodeServlet'/>" border="1"/>
		<a href="javascript: _change()">I can't see clearly. Change it</a><br />
		<input type="submit" value="Sign in"/>
		<a href="regist.jsp">No account? Register!</a>
	</form>
</body>
</html>
  • Then we create a Servlet class named VerifyCodeServlet to call the dynamically generated code image:
@WebServlet("/VerifyCodeServlet")
public class VerifyCodeServlet extends HttpServlet {


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/*
		 * 1. Create verification code class
		 */
		VerifyCode vc = new VerifyCode();
		/*
		 * 2. Get captcha picture
		 */
		BufferedImage image = vc.getImage();
		/*
		 * 3. Save the text on the picture to the session
		 */
		request.getSession().setAttribute("session_vcode", vc.getText());
		/*
		 * 4. Respond the picture to the client
		 */
		VerifyCode.output(image, response.getOutputStream());
	}

}

In this way, we not only save the image to the response, but also save the generated content, which is used to verify the image content

Run the interface with tomcat:

This is the picture we generated:

At the same time, you can use the previously saved data to verify whether it is successful

Click Change and call the method repeatedly to refresh:

Posted by Castle on Wed, 20 Nov 2019 08:43:47 -0800