java生成验证码
2011年7月3日
531,854 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"; } } }
Code很好, 我的一个问题是: 产生多少条干扰线条是最合适的呢?