Servlet 验证码工具类

Servlet 验证码工具类

前言

之前用到的一个验证码工具类。

一、验证码获取

直接访问该接口即可获取一个验证码,同时在session对象中放一个validCode属性,值为验证码的值。

package com.sheng.xianya.demo;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 验证码图片生成,同时将生成的验证码放入session的validCode属性中。
 */
@WebServlet("/demo/GetValidCodeServlet")
public class GetValidCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.创建图片。
        BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
        // 2.创建画板,并设置画笔颜色、绘画坐标。画之前需要拿到画笔。
        Graphics2D gra = img.createGraphics();
        gra.setColor(Color.WHITE);
        gra.fillRect(0, 0, 200, 100);
        // 3.随机数。
        // 数字数量(最大支持5个数字)
        int numberQuantity = 5;
        List<Integer> list = new ArrayList<>(numberQuantity);
        Random random = new Random();
        for (int i = 0; i < numberQuantity; i++) {
            list.add(random.nextInt(10));
        }
        // 4.设置字体、颜色。
        gra.setFont(new Font("宋体", Font.ITALIC | Font.BOLD, 40));
        Color[] colors = new Color[]{Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN, Color.PINK, Color.GRAY};
        // 5.遍历集合并设置数字随机颜色、位置。
        for (int i = 0; i < numberQuantity; i++) {
            gra.setColor(colors[random.nextInt(colors.length)]);
            gra.drawString(list.get(i) + "", i * 40, 70 + (random.nextInt(21) - 10));
        }
        // 6.遍历集合并设置干扰线随机颜色、位置。
        // 干扰线数量
        int lineQuantity = 3;
        for (int i = 0; i < lineQuantity; i++) {
            gra.setColor(colors[random.nextInt(colors.length)]);
            gra.drawLine(0, random.nextInt(101), 200, random.nextInt(101));
        }
        // 7.将验证码放入到session中。
        HttpSession session = req.getSession();
        session.setAttribute("validCode", getStr(list));
        // 8.获取响应流,并把生成的图片img设置为jpg格式后放入响应流中。
        ServletOutputStream out = resp.getOutputStream();
        ImageIO.write(img, "jpg", out);
    }

    /** 将集合中的数字转成字符串 */
    String getStr(List<Integer> list) {
    	StringBuilder s = new StringBuilder();
		for (Integer i : list) {
			s.append(i);
		}
		return s.toString();
	}
}

二、验证码测试

package com.sheng.xianya.demo;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用于处理validCodeTest.jsp页面的post请求。
 */
@WebServlet("/demo/TestValidCodeServlet")
public class TestValidCodeServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.getRequestDispatcher("validCodeTest.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1.获取参数
		request.setCharacterEncoding("utf-8");
		String code = request.getParameter("code");
		
		// 2.获取session对象中的验证码信息validCode
		String validCode = (String) request.getSession().getAttribute("validCode");
		
		// 3.校验
		String msg = "";
		if (code.equals(validCode)) {
			msg = "验证码正确!";
		} else {
			msg = "验证码错误!";
		}
		
		// 4.响应信息
		request.setAttribute("msg", msg);
		request.getRequestDispatcher("validCodeTest.jsp").forward(request, response);
	}

}

三、验证码页面

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>验证码</title>
</head>
<body>
<h1>验证码</h1>

	<form action="TestValidCodeServlet" method="post">
		<!-- 验证码开始 -->
		<input type="text" name="code" placeholder="验证码" required> <span style="color:red;">${msg }</span>
        <div>
	   		<img id="code" alt="未显示" src="GetValidCodeServlet" width="100" height="50" onclick="getSrc(this)">
			<span>点击图片切换验证码。</span>
			<script>
			    // 点击图片切换验证码
			    function getSrc(img) {
			        // src属性值中需要加一个时间戳参数。因为浏览器带有缓存功能,当一个src中的URL请求一次后,再次请求浏览器就不会再去请求获得新数据,而是直接用,上次请求返回的数据。
			        img.src = "GetValidCodeServlet?date=" + new Date();
			    }
			</script>
        </div>
        <!-- 验证码结束 -->
		<input type="submit" value="提交">
	</form>
</body>
</html>

四、另一个验证码工具类

这个可以生成有英文字母的验证码。

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

public final class ImageUtil {
	
	// 验证码字符集
	private static final char[] chars = { 
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
		'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
	// 字符数量
	private static final int SIZE = 4;
	// 干扰线数量
	private static final int LINES = 5;
	// 宽度
	private static final int WIDTH = 80;
	// 高度
	private static final int HEIGHT = 40;
	// 字体大小
	private static final int FONT_SIZE = 30;

	/**
	 * 生成随机验证码及图片
	 */
	public static Object[] createImage() {
		StringBuffer sb = new StringBuffer();
		// 1.创建空白图片
		BufferedImage image = new BufferedImage(
			WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		// 2.获取图片画笔
		Graphics graphic = image.getGraphics();
		// 3.设置画笔颜色
		graphic.setColor(Color.LIGHT_GRAY);
		// 4.绘制矩形背景
		graphic.fillRect(0, 0, WIDTH, HEIGHT);
		// 5.画随机字符
		Random ran = new Random();
		for (int i = 0; i <SIZE; i++) {
			// 取随机字符索引
			int n = ran.nextInt(chars.length);
			// 设置随机颜色
			graphic.setColor(getRandomColor());
			// 设置字体大小
			graphic.setFont(new Font(
				null, Font.BOLD + Font.ITALIC, FONT_SIZE));
			// 画字符
			graphic.drawString(
				chars[n] + "", i * WIDTH / SIZE, HEIGHT / 2);
			// 记录字符
			sb.append(chars[n]);
		}
		// 6.画干扰线
		for (int i = 0; i < LINES; i++) {
			// 设置随机颜色
			graphic.setColor(getRandomColor());
			// 随机画线
			graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
					ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
		}
		// 7.返回验证码和图片
		return new Object[]{sb.toString(), image};
	}

	/**
	 * 随机取色
	 */
	public static Color getRandomColor() {
		Random ran = new Random();
		Color color = new Color(ran.nextInt(256), 
				ran.nextInt(256), ran.nextInt(256));
		return color;
	}
	
	public static void main(String[] args) throws IOException {
		Object[] objs = createImage();
		BufferedImage image = (BufferedImage) objs[1];
		OutputStream os = new FileOutputStream("d:/1.jpg");
		ImageIO.write(image, "jpeg", os);
		os.close();
	}

}