大家在使用Web网站的时候,经常会发现有个验证码需要输入,这里验证码用来做什么事情呢?其实很简单,验证码图片的作用是让用户通过肉眼来观察图片,把图片中的内容填写到输入框中,在登录的时候,如果验证码内容输入不正确,就算你的登录用户名和密码都正确也不行,这样可以很好的防治有人用程序不停的猜测别人的帐号和密码,因为程序难以从一个图片中提取验证码的内容,从而难以使用程序来进行重复猜测,这样只是凭人工的办法,是很难在短时间内猜出帐号和密码的。所以验证码图片实际是为了保护用户的权益。那么到底如何在web开发中使用验证码图片呢?
    

     验证码图片是由程序动态产生的,每次访问的内容都是随机的。那么如何采用程序动态产生图片,并能够显示在客户端页面中呢?原理很简单,对于java而言,我们首先开发一个Servlet,这个Servlet的任务就是给客户端产生一个验证码图片的输入,示例代码如下:

  1. package com.web.servlet; 
  2. import java.awt.Color; 
  3. import java.awt.Graphics; 
  4. import java.awt.p_w_picpath.BufferedImage; 
  5. import java.io.IOException; 
  6. import javax.servlet.ServletException; 
  7. import javax.servlet.ServletOutputStream; 
  8. import javax.servlet.http.HttpServletRequest; 
  9. import javax.servlet.http.HttpServletResponse; 
  10. import com.sun.p_w_picpath.codec.jpeg.JPEGCodec; 
  11. import com.sun.p_w_picpath.codec.jpeg.JPEGImageEncoder; 
  12. public class ValidateImgServlet extends javax.servlet.http.HttpServlet implements 
  13. javax.servlet.Servlet { 
  14.     private static final long serialVersionUID = 1L
  15.  
  16.     protected void doGet(HttpServletRequest request, HttpServletResponse response) 
  17. throws ServletException, IOException { 
  18.         response.setContentType("p_w_picpath/jpeg"); 
  19.         
  20.         //产生四位验证码 
  21.         StringBuffer sb = new StringBuffer(4); 
  22.         for(int i=0; i<4; i++) { 
  23.             int n = (int)(Math.random() * 10); 
  24.             sb.append(n); 
  25.         } 
  26.         String validateCode = sb.toString(); 
  27.         //将验证码记录在session中,便于用户输入之后的验证 
  28.         request.getSession().setAttribute("ValidateCode", validateCode); 
  29.         
  30.         //创建缓存图片 
  31.         BufferedImage p_w_picpath = new BufferedImage(80, 25, BufferedImage.TYPE_INT_RGB); 
  32.         Graphics g = p_w_picpath.getGraphics(); 
  33.                     
  34.         g.setColor(Color.LIGHT_GRAY); 
  35.         g.fillRect(0, 0, 80, 25); 
  36.         g.setColor(Color.BLACK); 
  37.         g.drawString(validateCode, 10, 20); 
  38.         g.dispose(); 
  39.         ServletOutputStream outStream = response.getOutputStream(); 
  40.         JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outStream); 
  41.         encoder.encode(p_w_picpath); 
  42.         outStream.close(); 
  43.     }                      

在web.xml中对这个Servlet进行配置,配置信息如下:

  1. <servlet> 
  2.         <description></description> 
  3.         <display-name>ValidateImgServlet</display-name> 
  4.         <servlet-name>ValidateImgServlet</servlet-name> 
  5.         <servlet-class>com.web.servlet.ValidateImgServlet</servlet-class> 
  6.     </servlet> 
  7.     <servlet-mapping> 
  8.         <servlet-name>ValidateImgServlet</servlet-name> 
  9.         <url-pattern>/validateimg.jpg</url-pattern> 
  10.     </servlet-mapping> 

好了,现在我们可以在登录页面中使用这个动态的验证码图片了,login.jsp页面内容如下:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8" 
  2.     pageEncoding="UTF-8"%> 
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/
  4. loose.dtd"> 
  5. <html> 
  6. <head> 
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
  8. <title>Insert title here</title> 
  9. </head> 
  10. <body> 
  11.     请输入登录信息:<br /> 
  12.     <form name="login_form" method="post" action="login.action"> 
  13.     用户名称:<input type="text" name="username" /><br /> 
  14.     用户密码:<input type="password" name="password" /><br /> 
  15.     验证码:<input type="text" name="validatecode" /><img src="validateimg.jpg" border="0" />
  16. <br /> 
  17.     <input type="submit" value="登录" /> 
  18.     </form> 
  19. </body> 
  20. </html> 

到这里,如果你在web容器中运行这个jsp,你将会在浏览器中看见一个带有验证码图片的登录表单,后续的验证任务就交给你了。祝你好运!

Web开发中的验证码图片的生成-基于Java的实现_jsp

但是这个 验证码不是很美观,完全有理由弄得更真实些。修改代码:

  1. package com.servlet; 
  2.  
  3. import java.awt.Color; 
  4. import java.awt.Font; 
  5. import java.awt.Graphics2D; 
  6. import java.awt.p_w_picpath.BufferedImage; 
  7. import java.util.Random; 
  8. import javax.p_w_picpathio.ImageIO; 
  9. import javax.servlet.ServletException; 
  10. import javax.servlet.ServletOutputStream; 
  11. import javax.servlet.http.HttpServlet; 
  12. import javax.servlet.http.HttpServletRequest; 
  13. import javax.servlet.http.HttpServletResponse; 
  14. import javax.servlet.http.HttpSession; 
  15.  
  16. /** 
  17.  * 生成随机验证码 
  18.  *  
  19.  * @author bitiliu 
  20.  *  
  21.  */ 
  22. public class ValidateCodeServlet extends HttpServlet { 
  23.     private static final long serialVersionUID = 1L
  24.     // 验证码图片的宽度。 
  25.     private int width = 160
  26.     // 验证码图片的高度。 
  27.     private int height = 20
  28.     // 验证码字符个数 
  29.     private int codeCount = 4
  30.  
  31.     private int x = 0
  32.     // 字体高度 
  33.     private int fontHeight; 
  34.     private int codeY; 
  35.     char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 
  36.             'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 
  37.             'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 
  38.  
  39.     /** 
  40.      * 初始化验证图片属性 
  41.      */ 
  42.     public void init() throws ServletException { 
  43.         // 从web.xml中获取初始信息 
  44.         // 宽度 
  45.         String strWidth = this.getInitParameter("width"); 
  46.         // 高度 
  47.         String strHeight = this.getInitParameter("height"); 
  48.         // 字符个数 
  49.         String strCodeCount = this.getInitParameter("codeCount"); 
  50.         // 将配置的信息转换成数值 
  51.         try { 
  52.             if (strWidth != null && strWidth.length() != 0) { 
  53.                 width = Integer.parseInt(strWidth); 
  54.             } 
  55.             if (strHeight != null && strHeight.length() != 0) { 
  56.                 height = Integer.parseInt(strHeight); 
  57.             } 
  58.             if (strCodeCount != null && strCodeCount.length() != 0) { 
  59.                 codeCount = Integer.parseInt(strCodeCount); 
  60.             } 
  61.         } catch (NumberFormatException e) { 
  62.         } 
  63.         x = width / (codeCount + 1); 
  64.         fontHeight = height - 2; 
  65.         codeY = height - 4; 
  66.     } 
  67.  
  68.     protected void service(HttpServletRequest req, HttpServletResponse resp) 
  69.             throws ServletException, java.io.IOException { 
  70.         // 定义图像buffer 
  71.         BufferedImage buffImg = new BufferedImage(width, height, 
  72.                 BufferedImage.TYPE_INT_RGB); 
  73.         Graphics2D g = buffImg.createGraphics(); 
  74.         // 创建一个随机数生成器类 
  75.         Random random = new Random(); 
  76.         // 将图像填充为白色 
  77.         g.setColor(Color.WHITE); 
  78.         g.fillRect(0, 0, width, height); 
  79.         // 创建字体,字体的大小应该根据图片的高度来定。 
  80.         Font font = new Font("Fixedsys", Font.PLAIN, fontHeight); 
  81.         // 设置字体。 
  82.         g.setFont(font); 
  83.         // 画边框。 
  84.         g.setColor(Color.BLACK); 
  85.         g.drawRect(0, 0, width - 1, height - 1); 
  86.         // 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。 
  87.         g.setColor(Color.BLACK); 
  88.         for (int i = 0; i < 160; i++) { 
  89.             int x = random.nextInt(width); 
  90.             int y = random.nextInt(height); 
  91.             int xl = random.nextInt(12); 
  92.             int yl = random.nextInt(12); 
  93.             g.drawLine(x, y, x + xl, y + yl); 
  94.         } 
  95.         // randomCode用于保存随机产生的验证码,以便用户登录后进行验证。 
  96.         StringBuffer randomCode = new StringBuffer(); 
  97.         int red = 0green = 0blue = 0
  98.         // 随机产生codeCount数字的验证码。 
  99.         for (int i = 0; i < codeCount; i++) { 
  100.             // 得到随机产生的验证码数字。 
  101.             String strRand = String.valueOf(codeSequence[random.nextInt(36)]); 
  102.             // 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。 
  103.             red = random.nextInt(255); 
  104.             green = random.nextInt(255); 
  105.             blue = random.nextInt(255); 
  106.             // 用随机产生的颜色将验证码绘制到图像中。 
  107.             g.setColor(new Color(red, green, blue)); 
  108.             g.drawString(strRand, (i + 1) * x, codeY); 
  109.             // 将产生的四个随机数组合在一起。 
  110.             randomCode.append(strRand); 
  111.         } 
  112.         // 将四位数字的验证码保存到Session中。 
  113.         HttpSession session = req.getSession(); 
  114.         session.setAttribute("validateCode", randomCode.toString()); 
  115.         // 禁止图像缓存。 
  116.         resp.setHeader("Pragma", "no-cache"); 
  117.         resp.setHeader("Cache-Control", "no-cache"); 
  118.         resp.setDateHeader("Expires", 0); 
  119.         resp.setContentType("p_w_picpath/jpeg"); 
  120.         // 将图像输出到Servlet输出流中。 
  121.         ServletOutputStream sos = resp.getOutputStream(); 
  122.         ImageIO.write(buffImg, "jpeg", sos); 
  123.         sos.close(); 
  124.     } 

web.xml 内容为:

 

  1. <body> 
  2.     请输入登录信息:<br /> 
  3.     <form name="login_form" method="post" action="login.action"> 
  4.     用户名称:<input type="text" name="username" /><br /> 
  5.     用户密码:<input type="password" name="password" /><br /> 
  6.     验证码:<input type="text" name="validatecode" /><img src="validateCodeServlet" 
  7. border="0" /><br /> 
  8.     <input type="submit" value="登录" /> 
  9.     </form> 
  10. </body> 

Web开发中的验证码图片的生成-基于Java的实现_jsp_02