网友写的验证码生成方案,可防止绝大多数机械识别。

11/25/2015来源:ASP.NET技巧人气:1302

web.xml 
Xml代码  收藏代码
  1. <!DOCTYPE web-app PUBLIC  
  2.  "-//Sun Microsystems, Inc.//DTD Web application 2.3//EN"  
  3.  "http://java.sun.com/dtd/web-app_2_3.dtd" >  
  4.   
  5. <web-app>  
  6.     <!-- ******************************************** -->  
  7.     <!-- **********验证码生成器************************** -->  
  8.     <!-- ******************************************** -->  
  9.     <servlet>  
  10.         <servlet-name>CaptchaServlet</servlet-name>  
  11.         <servlet-class>com.lowca.activity.web.servlet.CaptchaServlet</servlet-class>  
  12.         <init-param>  
  13.             <param-name>width</param-name>  
  14.             <param-value>150</param-value>  
  15.         </init-param>  
  16.         <init-param>  
  17.             <param-name>height</param-name>  
  18.             <param-value>100</param-value>  
  19.         </init-param>  
  20.         <init-param>  
  21.             <param-name>bgColor</param-name>  
  22.             <param-value>255,255,255</param-value>  
  23.         </init-param>  
  24.         <init-param>  
  25.             <param-name>fontColor</param-name>  
  26.             <param-value>0,255,0</param-value>  
  27.         </init-param>  
  28.         <init-param>  
  29.             <param-name>fontSize</param-name>  
  30.             <param-value>44</param-value>  
  31.         </init-param>  
  32.         <init-param>  
  33.             <param-name>fontCount</param-name>  
  34.             <param-value>4</param-value>  
  35.         </init-param>  
  36.         <init-param>  
  37.             <param-name>fontName</param-name>  
  38.             <param-value>宋体</param-value>  
  39.         </init-param>  
  40.         <init-param>  
  41.             <param-name>chars</param-name>  
  42.             <!-- 去掉了容易造成误解的字符,例如:i o z 和 1 0 2 -->  
  43.             <param-value>ABCDEFGHJKLMNPQRSTUVWXYabcdefghjkmnpqrstuvwxy3456789</param-value>  
  44.         </init-param>  
  45.         <init-param>  
  46.             <param-name>sessionKey</param-name>  
  47.             <param-value>com.lowca.activity.captcha</param-value>  
  48.         </init-param>  
  49.         <init-param>  
  50.             <param-name>maxRotateAngle</param-name>  
  51.             <param-value>40</param-value>  
  52.         </init-param>  
  53.         <init-param>  
  54.             <param-name>fontPadding</param-name>  
  55.             <param-value>-15</param-value>  
  56.         </init-param>  
  57.     </servlet>  
  58.   
  59.     <servlet-mapping>  
  60.         <servlet-name>CaptchaServlet</servlet-name>  
  61.         <url-pattern>/captcha.jpg</url-pattern>  
  62.     </servlet-mapping>  
  63. </web-app>  
servlet类文件 
Java代码  收藏代码
  1. package com.lowca.activity.web.servlet;  
  2.   
  3. import java.awt.BasicStroke;  
  4. import java.awt.Color;  
  5. import java.awt.Font;  
  6. import java.awt.Graphics2D;  
  7. import java.awt.geom.AffineTransform;  
  8. import java.awt.image.BufferedImage;  
  9. import java.io.IOException;  
  10.   
  11. import javax.imageio.ImageIO;  
  12. import javax.servlet.ServletException;  
  13. import javax.servlet.ServletOutputStream;  
  14. import javax.servlet.http.HttpServlet;  
  15. import javax.servlet.http.HttpServletRequest;  
  16. import javax.servlet.http.HttpServletResponse;  
  17. import javax.servlet.http.HttpSession;  
  18.   
  19. import org.apache.commons.lang.StringUtils;  
  20. import org.apache.commons.lang.math.NumberUtils;  
  21.   
  22. public class CaptchaServlet extends HttpServlet {  
  23.   
  24.     PRivate static final long serialVersionUID = 1L;  
  25.   
  26.     private static final String CONTENT_TYPE = "image/jpeg";  
  27.   
  28.     // ==================以下变量用于保存配置参数的默认值 ==================  
  29.     /** 
  30.      * 验证码的宽度 
  31.      */  
  32.     private int width = 200;  
  33.     /** 
  34.      * 验证码的高度 
  35.      */  
  36.     private int height = 150;  
  37.     /** 
  38.      * 验证码背景色 
  39.      */  
  40.     private Color bgColor = Color.WHITE;  
  41.     /** 
  42.      * 文字颜色 
  43.      */  
  44.     private Color fontColor = Color.GREEN;  
  45.     /** 
  46.      * 验证码字符字号 
  47.      */  
  48.     private int fontSize = 42;  
  49.     /** 
  50.      * 验证码字符个数 
  51.      */  
  52.     private int fontCount = 4;  
  53.     /** 
  54.      * 验证码字符间距,单位是像素 
  55.      */  
  56.     private int fontPadding = -15;  
  57.     /** 
  58.      * 验证码字符最大旋转角度 
  59.      */  
  60.     private int maxRotateAngle = 40;  
  61.     /** 
  62.      * 验证码字体 
  63.      */  
  64.     private String fontName = "宋体";  
  65.     /** 
  66.      * 验证码用到的字符 
  67.      */  
  68.     private String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
  69.     /** 
  70.      * 验证码在session中的键名 
  71.      */  
  72.     private String sessionKey = "com.lowca.activity.captcha";  
  73.   
  74.     // ==================以下变量用于在初始化时候保存数据,减少重复计算 ==================  
  75.   
  76.     private Font font;  
  77.   
  78.     private char[] seedArray;  
  79.   
  80.     private int offsetX = 0;  
  81.   
  82.     private int offsetY = 0;  
  83.   
  84.     /** 
  85.      * 生成由数字和字母随机组成的图片 
  86.      */  
  87.     protected void service(HttpServletRequest req, HttpServletResponse resp)  
  88.             throws ServletException, java.io.IOException {  
  89.         BufferedImage buffImg = new BufferedImage(width, height,  
  90.                 BufferedImage.TYPE_INT_RGB);  
  91.         Graphics2D g2d = buffImg.createGraphics();  
  92.         g2d.setColor(bgColor);  
  93.         g2d.fillRect(0, 0, width, height);  
  94.         g2d.setPaint(fontColor);  
  95.         g2d.setFont(font);  
  96.         // 旋转文本  
  97.   
  98.         StringBuffer randCode = new StringBuffer();  
  99.         for (int i = 0; i < fontCount; i++) {  
  100.             g2d.setStroke(new BasicStroke((float) (Math.random() * 5)));  
  101.             double angle = Math.random() * maxRotateAngle * Math.PI / 180;  
  102.             int p = (int) (Math.random() * chars.length());  
  103.             String Word = String.valueOf(seedArray[p]);  
  104.             randCode.append(word);  
  105.             int x = offsetX + i * (fontSize + fontPadding);  
  106.   
  107.             AffineTransform origXform = g2d.getTransform();  
  108.             AffineTransform newXform = (AffineTransform) (origXform.clone());  
  109.             newXform.rotate(angle, x, offsetY);  
  110.             g2d.setTransform(newXform);  
  111.             g2d.drawString(word, x, offsetY);  
  112.             g2d.setTransform(origXform);  
  113.         }  
  114.         g2d.setStroke(new BasicStroke(2.0f));  
  115.         int x = offsetX - (int) (20 * Math.random());  
  116.         int y = offsetY - (int) (20 * Math.random());  
  117.         int w = (int) (width - 10 - Math.random() * 6);  
  118.         int h = (int) (height - 10 - Math.random() * 6);  
  119.         int startAngle = (int) (Math.random() * 16 + 45);  
  120.         int arcAngle = (int) (Math.random() * 45 + 90);  
  121.         g2d.drawArc(x, y, w, h, startAngle, arcAngle);  
  122.         g2d.dispose();  
  123.   
  124.         // 将四位数字的验证码保存到Session里面  
  125.         HttpSession session = req.getSession();  
  126.         session.setAttribute(sessionKey, randCode);  
  127.   
  128.         // 禁止图像缓存  
  129.         resp.setHeader("Prama", "no-cache");  
  130.         resp.setHeader("Coche-Control", "no-cache");  
  131.         resp.setDateHeader("Expires", 0);  
  132.   
  133.         // 将图像输出到Servelt输出流中  
  134.         ServletOutputStream out = resp.getOutputStream();  
  135.         ImageIO.write(buffImg, "jpeg", out);  
  136.         out.close();  
  137.     }  
  138.   
  139.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  140.             throws ServletException, IOException {  
  141.         doGet(request, response);  
  142.     }  
  143.   
  144.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  145.             throws ServletException, IOException {  
  146.         response.setContentType(CONTENT_TYPE);  
  147.     }  
  148.   
  149.     public void init() throws ServletException {  
  150.         // 初始化配置参数  
  151.         String param = getInitParameter("width");  
  152.         if (NumberUtils.isDigits(param)) {  
  153.             width = Integer.parseInt(param);  
  154.         }  
  155.         param = getInitParameter("height");  
  156.         if (NumberUtils.isDigits(param)) {  
  157.             height = Integer.parseInt(param);  
  158.         }  
  159.         param = getInitParameter("bgColor");  
  160.         if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {  
  161.             bgColor = getColor(param);  
  162.         }  
  163.         param = getInitParameter("fontColor");  
  164.         if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {  
  165.             fontColor = getColor(param);  
  166.         }  
  167.         param = getInitParameter("fontSize");  
  168.         if (NumberUtils.isDigits(param)) {  
  169.             fontSize = Integer.parseInt(param);  
  170.         }  
  171.         param = getInitParameter("maxRotateAngle");  
  172.         if (NumberUtils.isDigits(param)) {  
  173.             maxRotateAngle = Integer.parseInt(param);  
  174.         }  
  175.         param = getInitParameter("fontPadding");  
  176.         if (param != null && param.matches("-?\\d+")) {  
  177.             fontPadding = Integer.parseInt(param);  
  178.         }  
  179.         param = getInitParameter("fontName");  
  180.         if (StringUtils.isNotBlank(param)) {  
  181.             fontName = param;  
  182.         }  
  183.         param = getInitParameter("chars");  
  184.         if (StringUtils.isNotBlank(param)) {  
  185.             chars = param;  
  186.         }  
  187.         param = getInitParameter("sessionKey");  
  188.         if (StringUtils.isNotBlank(sessionKey)) {  
  189.             sessionKey = param;  
  190.         }  
  191.         // 初始化状态变量  
  192.         font = new Font(fontName, Font.ITALIC, fontSize);  
  193.         seedArray = chars.toCharArray();  
  194.         offsetX = width / 2 - fontCount * fontSize / 2 - (fontCount - 1)  
  195.                 * fontPadding / 2 - 8;  
  196.         offsetY = height / 2 + fontSize / 2 - 8;  
  197.     }  
  198.   
  199.     private Color getColor(String rgb) {  
  200.         String[] array = rgb.split(",");  
  201.         return new Color(Integer.parseInt(array[0]),  
  202.                 Integer.parseInt(array[1]), Integer.parseInt(array[2]));  
  203.     }  
  204.   
  205. }  
在我的机器上,这个程序每秒钟可以产生大约83张验证码。验证码图样如下
  • 大小: 2.6 KB
  • 大小: 2.5 KB
  • 大小: 2.4 KB
  • 大小: 2.4 KB