我写的验证码生成方案,可防止绝大多数机械识别。
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><!-- ******************************************** --><!-- **********验证码生成器************************** --><!-- ******************************************** --><servlet><servlet-name>CaptchaServlet</servlet-name><servlet-class>com.lowca.activity.web.servlet.CaptchaServlet</servlet-class><init-param><param-name>width</param-name><param-value>150</param-value></init-param><init-param><param-name>height</param-name><param-value>100</param-value></init-param><init-param><param-name>bgColor</param-name><param-value>255,255,255</param-value></init-param><init-param><param-name>fontColor</param-name><param-value>0,255,0</param-value></init-param><init-param><param-name>fontSize</param-name><param-value>44</param-value></init-param><init-param><param-name>fontCount</param-name><param-value>4</param-value></init-param><init-param><param-name>fontName</param-name><param-value>宋体</param-value></init-param><init-param><param-name>chars</param-name><!-- 去掉了容易造成误解的字符,例如:i o z 和 1 0 2 --><param-value>ABCDEFGHJKLMNPQRSTUVWXYabcdefghjkmnpqrstuvwxy3456789</param-value></init-param><init-param><param-name>sessionKey</param-name><param-value>com.lowca.activity.captcha</param-value></init-param><init-param><param-name>maxRotateAngle</param-name><param-value>40</param-value></init-param><init-param><param-name>fontPadding</param-name><param-value>-15</param-value></init-param></servlet><servlet-mapping><servlet-name>CaptchaServlet</servlet-name><url-pattern>/captcha.jpg</url-pattern></servlet-mapping></web-app>
package com.lowca.activity.web.servlet;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.geom.AffineTransform;import java.awt.image.BufferedImage;import java.io.IOException;import javax.imageio.ImageIO;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang.math.NumberUtils;public class CaptchaServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static final String CONTENT_TYPE = "image/jpeg";// ==================以下变量用于保存配置参数的默认值 ==================/** * 验证码的宽度 */private int width = 200;/** * 验证码的高度 */private int height = 150;/** * 验证码背景色 */private Color bgColor = Color.WHITE;/** * 文字颜色 */private Color fontColor = Color.GREEN;/** * 验证码字符字号 */private int fontSize = 42;/** * 验证码字符个数 */private int fontCount = 4;/** * 验证码字符间距,单位是像素 */private int fontPadding = -15;/** * 验证码字符最大旋转角度 */private int maxRotateAngle = 40;/** * 验证码字体 */private String fontName = "宋体";/** * 验证码用到的字符 */private String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";/** * 验证码在session中的键名 */private String sessionKey = "com.lowca.activity.captcha";// ==================以下变量用于在初始化时候保存数据,减少重复计算 ==================private Font font;private char[] seedArray;private int offsetX = 0;private int offsetY = 0;/** * 生成由数字和字母随机组成的图片 */protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, java.io.IOException {BufferedImage buffImg = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2d = buffImg.createGraphics();g2d.setColor(bgColor);g2d.fillRect(0, 0, width, height);g2d.setPaint(fontColor);g2d.setFont(font);// 旋转文本StringBuffer randCode = new StringBuffer();for (int i = 0; i < fontCount; i++) {g2d.setStroke(new BasicStroke((float) (Math.random() * 5)));double angle = Math.random() * maxRotateAngle * Math.PI / 180;int p = (int) (Math.random() * chars.length());String word = String.valueOf(seedArray[p]);randCode.append(word);int x = offsetX + i * (fontSize + fontPadding);AffineTransform origXform = g2d.getTransform();AffineTransform newXform = (AffineTransform) (origXform.clone());newXform.rotate(angle, x, offsetY);g2d.setTransform(newXform);g2d.drawString(word, x, offsetY);g2d.setTransform(origXform);}g2d.setStroke(new BasicStroke(2.0f));int x = offsetX - (int) (20 * Math.random());int y = offsetY - (int) (20 * Math.random());int w = (int) (width - 10 - Math.random() * 6);int h = (int) (height - 10 - Math.random() * 6);int startAngle = (int) (Math.random() * 16 + 45);int arcAngle = (int) (Math.random() * 45 + 90);g2d.drawArc(x, y, w, h, startAngle, arcAngle);g2d.dispose();// 将四位数字的验证码保存到Session里面HttpSession session = req.getSession();session.setAttribute(sessionKey, randCode);// 禁止图像缓存resp.setHeader("Prama", "no-cache");resp.setHeader("Coche-Control", "no-cache");resp.setDateHeader("Expires", 0);// 将图像输出到Servelt输出流中ServletOutputStream out = resp.getOutputStream();ImageIO.write(buffImg, "jpeg", out);out.close();}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType(CONTENT_TYPE);}public void init() throws ServletException {// 初始化配置参数String param = getInitParameter("width");if (NumberUtils.isDigits(param)) {width = Integer.parseInt(param);}param = getInitParameter("height");if (NumberUtils.isDigits(param)) {height = Integer.parseInt(param);}param = getInitParameter("bgColor");if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {bgColor = getColor(param);}param = getInitParameter("fontColor");if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {fontColor = getColor(param);}param = getInitParameter("fontSize");if (NumberUtils.isDigits(param)) {fontSize = Integer.parseInt(param);}param = getInitParameter("maxRotateAngle");if (NumberUtils.isDigits(param)) {maxRotateAngle = Integer.parseInt(param);}param = getInitParameter("fontPadding");if (param != null && param.matches("-?\\d+")) {fontPadding = Integer.parseInt(param);}param = getInitParameter("fontName");if (StringUtils.isNotBlank(param)) {fontName = param;}param = getInitParameter("chars");if (StringUtils.isNotBlank(param)) {chars = param;}param = getInitParameter("sessionKey");if (StringUtils.isNotBlank(sessionKey)) {sessionKey = param;}// 初始化状态变量font = new Font(fontName, Font.ITALIC, fontSize);seedArray = chars.toCharArray();offsetX = width / 2 - fontCount * fontSize / 2 - (fontCount - 1)* fontPadding / 2 - 8;offsetY = height / 2 + fontSize / 2 - 8;}private Color getColor(String rgb) {String[] array = rgb.split(",");return new Color(Integer.parseInt(array[0]),Integer.parseInt(array[1]), Integer.parseInt(array[2]));}}