首页 > java > java生成验证码

java生成验证码

2011年7月3日 563,041 views

一般分为如下几个步骤(顺序可变):

获取验证码
    前端:
    1.验证码在浏览器里,是一个img标签,将img的src设置为url请求即可
    后台:
    2.设置验证码中可能出现的字符
    3.画图片
        3.1创建BufferedImage对象
        3.2生成graphics对象
        3.3背景色
        3.4边框
        3.5干扰线
        3.6设置字体,画验证码
    4.设置response相关参数
    5.存session
    6.将图像输出到浏览器

检验验证码
    7.获取session中存储的字符串,进行验证
    8.如正确,将session中的存储清除

下面给出一个版本,可以点击下载

package org.fyc.test;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 
 * @author fyc 20110518
 * 
 */
public class CheckCodeGenerator {

	private static final CheckCodeGenerator generator = new CheckCodeGenerator();

	private final String ATTRIBUTE_NAME = "checkCode";
	// 图片的宽度
	private final int WIDTH = 15;
	// 图片的高度
	private final int HEIGHT = 22;
	// 字符串长度
	private final int CODE_LENGTH = 4;
	// 随机字符串范围
	private final String RAND_RANGE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
			+ "1234567890";
	private final char[] CHARS = RAND_RANGE.toCharArray();

	private Random random = new Random();

	private CheckCodeGenerator() {
		//
	}

	public static CheckCodeGenerator getInstance() {
		return generator;
	}

	/**
	 * 生成随机字符串
	 * 
	 * @return 随机字符串
	 */
	private String getRandString() {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < CODE_LENGTH; i++)
			sb.append(CHARS[random.nextInt(CHARS.length)]);
		return sb.toString();
	}

	/**
	 * 生成随机颜色
	 * 
	 * @param ll
	 *            产生颜色值下限(lower limit)
	 * @param ul
	 *            产生颜色值上限(upper limit)
	 * @return 生成的随机颜色对象
	 */
	private Color getRandColor(int ll, int ul) {
		if (ll > 255)
			ll = 255;
		if (ll < 1)
			ll = 1;
		if (ul > 255)
			ul = 255;
		if (ul < 1)
			ul = 1;
		if (ul == ll)
			ul = ll + 1;
		int r = random.nextInt(ul - ll) + ll;
		int g = random.nextInt(ul - ll) + ll;
		int b = random.nextInt(ul - ll) + ll;
		Color color = new Color(r, g, b);
		return color;
	}

	/**
	 * 生成指定字符串的图像数据
	 * 
	 * @param checkCode
	 *            即将被打印的随机字符串
	 * @return 生成的图像数据
	 * */
	private BufferedImage getImage(String checkCode) {

		BufferedImage image = new BufferedImage(WIDTH * CODE_LENGTH, HEIGHT,
				BufferedImage.TYPE_INT_RGB);

		// 获取图形上下文
		Graphics graphics = image.getGraphics();

		// 设置背景色
		graphics.setColor(getRandColor(150, 230));
		// 填充背景色
		graphics.fillRect(0, 0, WIDTH * 4, HEIGHT);

		// 设置边框颜色
		graphics.setColor(new Color(245, 245, 245));
		// 画边框
		for (int i = 0; i < 2; i++)
			graphics.drawRect(i, i, WIDTH * CODE_LENGTH - i * 2 - 1, HEIGHT - i
					* 2 - 1);

		// 设置随机干扰线条颜色
		graphics.setColor(getRandColor(130, 160));
		// 产生50条干扰线条
		for (int i = 0; i < 50; i++) {
			int x1 = random.nextInt(WIDTH * CODE_LENGTH - 4) + 2;
			int y1 = random.nextInt(HEIGHT - 4) + 2;
			int x2 = random.nextInt(WIDTH * CODE_LENGTH - 2 - x1) + x1;
			int y2 = y1;
			graphics.drawLine(x1, y1, x2, y2);
		}

		// 设置字体
		graphics.setFont(new Font("Times New Roman", Font.PLAIN, 18));
		// 画字符串
		for (int i = 0; i < this.CODE_LENGTH; i++) {
			String temp = checkCode.substring(i, i + 1);
			graphics.setColor(getRandColor(10, 40));
			graphics.drawString(temp, 13 * i + 6, 16);
		}

		// 图像生效
		graphics.dispose();

		return image;
	}

	/**
	 * 将验证码的图像输出
	 * 
	 * @param request
	 *            用户的请求对象
	 * @param response
	 *            用户的响应对象
	 * */
	public static void printImage(HttpServletRequest request,
			HttpServletResponse response) {

		// 将ContentType设为"image/jpeg",让浏览器识别图像格式。
		response.setContentType("image/jpeg");
		// 设置页面不缓存
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 2000);

		// 获得随机验证码
		String checkCode = generator.getRandString();
		// 获得验证码的图像数据
		BufferedImage bi = generator.getImage(checkCode);
		// 把验证码存入session
		request.getSession().setAttribute(generator.ATTRIBUTE_NAME, checkCode);
		try {
			// 获得Servlet输出流
			ServletOutputStream outStream = response.getOutputStream();
			// 创建可用来将图像数据编码为JPEG数据流的编码器
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outStream);
			// 将图像数据进行编码
			encoder.encode(bi);
			// 强行将缓冲区的内容输入到页面
			outStream.flush();
			// 关闭输出流
			outStream.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 检查输入的验证码是否正确
	 * 
	 * @param request
	 * @return 验证结果
	 * */
	public static String verify(HttpServletRequest request,
			HttpServletResponse response) {
		if (((String) request.getParameter(generator.ATTRIBUTE_NAME))
				.equalsIgnoreCase((String) request.getSession().getAttribute(
						generator.ATTRIBUTE_NAME))) {
			request.getSession().removeAttribute(generator.ATTRIBUTE_NAME);
			try {
				response.getWriter().write("success");
			} catch (IOException e) {
				e.printStackTrace();
			}
			return "success";
		} else {
			try {
				response.getWriter().write("error");
			} catch (IOException e) {
				e.printStackTrace();
			}
			return "error";
		}
	}
}

分类: java 标签:
  1. 2013年12月25日15:31 | #1

    Code很好, 我的一个问题是: 产生多少条干扰线条是最合适的呢?