JAVA实现验证码

来源:互联网 发布:shopnc源码下载2017 编辑:程序博客网 时间:2024/06/06 12:35

一、主要功能:

1、支持纯数字、大写字母、小写字母,及两两混合或三者混合类型验证码;

2、支持自定义特殊字符排除(如0oOi1jI);

3、支持图片及文字两种类型验证码;

4、支持自定义验证码图片大小;

5、支持自定义干扰线条数;

6、支持自定义及随机定义图片、文字、干扰线颜色;

其他:示例页面提供了<iframe>和<img>两种页面显示验证码的方式。

a、仅阿拉伯数字

 

二、主要代码

1.index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title><%=basePath%></title>
    </head>
  <script type="text/javascript">
    var req;
 
    //提交留言
    function pubMsg(){
        msgTitle   = document.msgForm.msgTitle.value;
        msgContent = document.msgForm.msgContent.value;
        verifyCode = document.msgForm.verifyCode.value;
     
        //检查输入内容格式
        if(msgTitle.length<5||msgContent.length<5){
            alert("标题和内容不能少于5个字符");
            return;
        }
        if(verifyCode.length==0){
          alert("请输入验证码");
          return;
        }
   
        //获得 XMLHttpRequest对象
        if(window.XMLHttpRequest)
            req=new XMLHttpRequest();
        else if(window.ActiveXObject)
            req=new ActiveXObject("Microsoft.XMLHTTP");
   
        //提交请求
        if(req){
          req.onreadystatechange=callBack;//指定服务器响应结果处理函数(注意仅函数名无括号)
          url="<%=path%>/servlet/PubMsgServlet?msgTitle="+msgTitle+"&msgContent="+msgContent+"&verifyCode="+verifyCode;
          req.open("GET",url,false);
          req.send();
      }
  }
 
  //服务器响应结果处理函数
  function callBack(){
      if(req.readyState==4){
          if(req.status==200){
              next=req.responseText;//获得服务器处理结果
              if(next=="this"){
                  alert("验证码不正确,请重新输入");
                  verifyCodeFrame.location.reload();//刷新验证码
              }else{
                  document.msgForm.msgTitle.value="";
                  document.msgForm.msgContent.value="";
                  window.location=next;//跳转页面
              }
          }else{
              alert(req.status+":"+req.statusText);
          }
      }
      document.msgForm.verifyCode.value="";
  }
 
  //更换验证码
  function changeVerifyCode(){
      //1、如果用<iframe>实现,则重新加载<iframe>的内容
      //verifyCodeFrame.location.reload();
     
      //2、如果用<img>实现,则修改<img src=url>的url
      //这里有一个小技巧,如果给url赋相同的值,浏览器不会重新发出请求,因此用js生成一个即时毫秒数做url中的参数
      t=new Date().getTime();
      document.msgForm.verifyCodeImg.src="<%=path%>/servlet/VerifyCodeServlet?t="+t;
  }
  </script>
<body>
  <form name="msgForm" action="" method="post">
    <table border=0>
        <tr>
            <td>标题:</td>
            <td><input name="msgTitle" size="65" /></td>
        </tr>
        <tr>
            <td>内容:</td>
            <td><textarea name="msgContent" rows="10" cols="64"></textarea></td>
        </tr>
        <tr>
            <td>验证码:</td>
            <td>
              <input name="verifyCode"  style="height: 29px; width =70px; font-size: 25px" />

              <!-- 以下:两种显示验证码的方式 -->

              <!-- 1、采用<iframe>实现 -->
              <!--
                  <iframe name="verifyCodeFrame" src="<%=path + "/servlet/VerifyCodeServlet"%>"
                width="100" height="30" frameborder=0 align="top" marginheight=0 marginwidth=0 scrolling=no></iframe>
                 -->
              <!-- 2、采用<img>实现 -->
              <img name="verifyCodeImg" src="<%=path%>/servlet/VerifyCodeServlet" style="cursor:hand" align="align" onClick="changeVerifyCode()" />

              <!-- 以上:两种显示验证码的方式 -->

              <font style="color: blue;"><a href="javascript:changeVerifyCode()">看不清?</a> </font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              <input type="button" value=" 发表留言 " onClick="pubMsg()" />
          </td>
    </tr>
  </table>
</form>
</body>
</html>

 

 

2.org.javachina.util.VerifyCode.java

package org.javachina.util;

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

/**
 * 验证码生成器类,可生成数字、大写、小写字母及三者混合类型的验证码。 支持自定义验证码字符数量; 支持自定义验证码图片的大小; 支持自定义需排除的特殊字符;
 * 支持自定义干扰线的数量; 支持自定义验证码图文颜色
 *
 * @author org.javachina
 * @version 1.01
 */
public class VerifyCode {

    /**
     * 验证码类型为仅数字 0~9
     */
    public static final int TYPE_NUM_ONLY = 0;

    /**
     * 验证码类型为仅字母,即大写、小写字母混合
     */
    public static final int TYPE_LETTER_ONLY = 1;

    /**
     * 验证码类型为数字、大写字母、小写字母混合
     */
    public static final int TYPE_ALL_MIXED = 2;

    /**
     * 验证码类型为数字、大写字母混合
     */
    public static final int TYPE_NUM_UPPER = 3;

    /**
     * 验证码类型为数字、小写字母混合
     */
    public static final int TYPE_NUM_LOWER = 4;

    /**
     * 验证码类型为仅大写字母
     */
    public static final int TYPE_UPPER_ONLY = 5;

    /**
     * 验证码类型为仅小写字母
     */
    public static final int TYPE_LOWER_ONLY = 6;

    private VerifyCode() {
    }

    /**
     * 生成验证码字符串
     *
     * @param type
     *            验证码类型,参见本类的静态属性
     * @param length
     *            验证码长度,大于0的整数
     * @param exChars
     *            需排除的特殊字符(仅对数字、字母混合型验证码有效,无需排除则为 null)
     * @return 验证码字符串
     */
    public static String generateTextCode(int type, int length, String exChars) {

        if (length <= 0)
            return "";

        StringBuffer code = new StringBuffer();
        int i = 0;
        Random r = new Random();

        switch (type) {

        // 仅数字
        case TYPE_NUM_ONLY:
            while (i < length) {
                int t = r.nextInt(10);
                if (exChars == null || exChars.indexOf(t + "") < 0) {// 排除特殊字符
                    code.append(t);
                    i++;
                }
            }
            break;

        // 仅字母(即大写字母、小写字母混合)
        case TYPE_LETTER_ONLY:
            while (i < length) {
                int t = r.nextInt(123);
                if ((t >= 97 || (t >= 65 && t <= 90)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        // 数字、大写字母、小写字母混合
        case TYPE_ALL_MIXED:
            while (i < length) {
                int t = r.nextInt(123);
                if ((t >= 97 || (t >= 65 && t <= 90) || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        // 数字、大写字母混合
        case TYPE_NUM_UPPER:
            while (i < length) {
                int t = r.nextInt(91);
                if ((t >= 65 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        // 数字、小写字母混合
        case TYPE_NUM_LOWER:
            while (i < length) {
                int t = r.nextInt(123);
                if ((t >= 97 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        // 仅大写字母
        case TYPE_UPPER_ONLY:
            while (i < length) {
                int t = r.nextInt(91);
                if ((t >= 65) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        // 仅小写字母
        case TYPE_LOWER_ONLY:
            while (i < length) {
                int t = r.nextInt(123);
                if ((t >= 97) && (exChars == null || exChars.indexOf((char) t) < 0)) {
                    code.append((char) t);
                    i++;
                }
            }
            break;

        }

        return code.toString();
    }

    /**
     * 已有验证码,生成验证码图片
     *
     * @param textCode
     *            文本验证码
     * @param width
     *            图片宽度
     * @param height
     *            图片高度
     * @param interLine
     *            图片中干扰线的条数
     * @param randomLocation
     *            每个字符的高低位置是否随机
     * @param backColor
     *            图片颜色,若为null,则采用随机颜色
     * @param foreColor
     *            字体颜色,若为null,则采用随机颜色
     * @param lineColor
     *            干扰线颜色,若为null,则采用随机颜色
     * @return 图片缓存对象
     */
    public static BufferedImage generateImageCode(String textCode, int width, int height, int interLine, boolean randomLocation, Color backColor,
            Color foreColor, Color lineColor) {

        BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = bim.getGraphics();

        // 画背景图
        g.setColor(backColor == null ? getRandomColor() : backColor);
        g.fillRect(0, 0, width, height);

        // 画干扰线
        Random r = new Random();
        if (interLine > 0) {

            int x = 0, y = 0, x1 = width, y1 = 0;
            for (int i = 0; i < interLine; i++) {
                g.setColor(lineColor == null ? getRandomColor() : lineColor);
                y = r.nextInt(height);
                y1 = r.nextInt(height);

                g.drawLine(x, y, x1, y1);
            }
        }

        // 写验证码

        // g.setColor(getRandomColor());
        // g.setColor(isSimpleColor?Color.BLACK:Color.WHITE);

        // 字体大小为图片高度的80%
        int fsize = (int) (height * 0.8);
        int fx = height - fsize;
        int fy = fsize;

        g.setFont(new Font(Font.DIALOG, Font.PLAIN, fsize));

        // 写验证码字符
        for (int i = 0; i < textCode.length(); i++) {
            fy = randomLocation ? (int) ((Math.random() * 0.3 + 0.6) * height) : fy;// 每个字符高低是否随机
            g.setColor(foreColor == null ? getRandomColor() : foreColor);
            g.drawString(textCode.charAt(i) + "", fx, fy);
            fx += fsize * 0.9;
        }

        g.dispose();

        return bim;
    }

    /**
     * 生成图片验证码
     *
     * @param type
     *            验证码类型,参见本类的静态属性
     * @param length
     *            验证码字符长度,大于0的整数
     * @param exChars
     *            需排除的特殊字符
     * @param width
     *            图片宽度
     * @param height
     *            图片高度
     * @param interLine
     *            图片中干扰线的条数
     * @param randomLocation
     *            每个字符的高低位置是否随机
     * @param backColor
     *            图片颜色,若为null,则采用随机颜色
     * @param foreColor
     *            字体颜色,若为null,则采用随机颜色
     * @param lineColor
     *            干扰线颜色,若为null,则采用随机颜色
     * @return 图片缓存对象
     */
    public static BufferedImage generateImageCode(int type, int length, String exChars, int width, int height, int interLine, boolean randomLocation,
            Color backColor, Color foreColor, Color lineColor) {

        String textCode = generateTextCode(type, length, exChars);
        BufferedImage bim = generateImageCode(textCode, width, height, interLine, randomLocation, backColor, foreColor, lineColor);

        return bim;
    }

    /**
     * 产生随机颜色
     *
     * @return
     */
    private static Color getRandomColor() {
        Random r = new Random();
        Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
        return c;
    }

    public static void main(String[] args) {

    }

}

 

 

3.org.javachina.servlet.VerifyCodeServlet.java

package org.javachina.servlet;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.javachina.util.VerifyCode;

public class VerifyCodeServlet extends HttpServlet {

    public VerifyCodeServlet() {
        super();
    }

    public void destroy() {
        super.destroy();
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置浏览器不缓存本页
        response.setHeader("Cache-Control", "no-cache");

        // 生成验证码,写入用户session
        String verifyCode = VerifyCode.generateTextCode(VerifyCode.TYPE_UPPER_ONLY, 4, null);
        request.getSession().setAttribute("verifyCode", verifyCode);

        // 输出验证码给客户端
        response.setContentType("image/jpeg");
        BufferedImage bim = VerifyCode.generateImageCode(verifyCode, 60, 20, 3, true, Color.WHITE, Color.BLACK, null);
        ImageIO.write(bim, "JPEG", response.getOutputStream());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    public void init() throws ServletException {
    }

}

 

 

4.org.javachina.servlet.PubMsgServlet.java

package org.javachina.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PubMsgServlet extends HttpServlet {
    public PubMsgServlet() {
        super();
    }

    public void destroy() {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 得到留言标题、内容及用户输入的验证码
        String msgTitle   = request.getParameter("msgTitle");
        String msgContent = request.getParameter("msgContent");
        String verifyCode = request.getParameter("verifyCode");

        // 取session中的正确验证码
        String legalCode = null;
        if (request.getSession().getAttribute("verifyCode") != null)
            legalCode = (String) (request.getSession().getAttribute("verifyCode"));

        String next;

        // 比较session中的验证码与用户输入是否一致(这里忽略了大小写)
        if (verifyCode != null && verifyCode.equalsIgnoreCase(legalCode)) {

            /*
             * 保存留言内容(省略)
             */

            // 指定下一个URL
            next = request.getContextPath() + "/ok.jsp";

        } else
            next = "this";

        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        out.print(next);
        out.flush();
        out.close();

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    public void init() throws ServletException {
    }

}

 

5. ok.jsp

  <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   <html>
    <body>
            您的留言已提交!<input type="button" value=" OK " onClick="window.history.go(-1)"/><br>
    </body>
    </html>



6.修改web.xml   添加如下内容:

  <servlet>
    <servlet-name>VerifyCodeServlet</servlet-name>
    <servlet-class>org.javachina.servlet.VerifyCodeServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>PubMsgServlet</servlet-name>
    <servlet-class>org.javachina.servlet.PubMsgServlet</servlet-class>
  </servlet>


  <servlet-mapping>
    <servlet-name>VerifyCodeServlet</servlet-name>
    <url-pattern>/servlet/VerifyCodeServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>PubMsgServlet</servlet-name>
    <url-pattern>/servlet/PubMsgServlet</url-pattern>
  </servlet-mapping>

 

 

转载地址:  http://www.java3z.com/cwbwebhome/article/article3/3468.html?id=2132