Java通用驗證碼程序及應用示例(提供源碼下載)

          把之前項目中寫的一個Java通用驗證碼程序整理了一下,與大家分享,希望能拋磚引玉。

          一、主要功能:

          1、支持純數字、大寫字母、小寫字母,及兩兩混合或三者混合類型驗證碼;

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

          3、支持圖片及文字兩種類型驗證碼;

          4、支持自定義驗證碼圖片大小;

          5、支持自定義干擾線條數;

          6、支持自定義及隨機定義圖片、文字、干擾線顏色;


          其他:示例頁面提供了<iframe>和<img>兩種頁面顯示驗證碼的方式。


          a、僅阿拉伯數字

          b、僅字母(大小寫混合)

          c、僅小寫字母

          d、僅大寫字母

          d、數字與小寫字母混合

          e、數字與大寫字母混合

          f、數字與大小寫字母混合

          g、自定義字符顏色(或隨機)

          h、自定義圖片顏色(或隨機)

          i、自定義干擾線的條數及顏色(或隨機)

          j、自定義驗證碼圖片大小

          k、自定義需排除的特殊字符(如0o等難分辨字符)


          二、代碼說明:

          1、pubMsg.jsp 發表留言頁面,實現<iframe>和<img>兩種顯示驗證碼方式,及ajax提交功能


          <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
          <%
          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="top" onClick="changeVerifyCode()"/>
            
            
          <!-- 以上:兩種顯示驗證碼的方式 -->
            
            
            
          <font style="color:blue;font-size=14"><href="javascript:changeVerifyCode()">看不清?</a></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            
          <input type="button" value=" 發表留言 " onClick="pubMsg()"/></td></tr>

            
          </table>
            
          </form>
            
            
          </body>
            
          </html>


          2、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>

          3、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<=0return "";
                  
                  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);
                      }
                  }
                  
                  
          //寫驗證碼
                  
                  
          //字體大小為圖片高度的80%
                  int fsize=(int)(height*0.8);
                 
          int fx=0;
                  
          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+=(width / textCode.length()) * (Math.random() * 0.3 + 0.8); //星風兄的高見,依據寬度浮動
                  }

                  
                  g.dispose();
                  
                  
          return bim;
              }

              
              
          /**
               * 產生隨機顏色
               * 
          @return
               
          */
              
          private static Color getRandomColor(){
                  Random r
          =new Random();
                  Color c
          =new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));
                  
          return c;
              }
            


          }

          4、org.javachina.servlet.VerifyCodeServlet.java 接受客戶端請求,向客戶端輸出驗證碼
              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, 90303,true,Color.WHITE,Color.BLACK,null);
                  ImageIO.write(bim, 
          "JPEG",response.getOutputStream());    
                  
              }

          5、org.javachina.servlet.PubMsgServlet.java 保存留言信息(比對驗證碼)
              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();
                  
              }


          以上源碼、文檔下載地址: http://download.csdn.net/source/1851509

          以上,望拋磚引玉,歡迎交流:hufoking@hotmail.com!



          posted on 2009-11-27 14:03 IknowIT 閱讀(4052) 評論(13)  編輯  收藏

          評論

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-27 17:09 零全零美

          多謝博主寫出這么好的總結,如果能加上漢字驗證碼,會更完美!  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-27 17:14 鵬飛liu

          我最近也要用到驗證碼,但是不知道是直接調用jsp文件的形式還是servlet方式好一些,請指教!謝謝  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載)[未登錄] 2009-11-27 17:15 IKnowIT

          多謝零全零美的建議!有時間把漢字驗證碼功能以及背景圖片隨機打點功能加上。  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載)[未登錄] 2009-11-27 17:17 IKnowIT

          @鵬飛liu
          也可以在jsp里直接寫代碼(或調用其他類)生成驗證碼,我習慣把這類的功能封裝成工具類,便于在各種情況下重用。  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-28 23:10 bzp

          不用session來傳遞驗證碼,行不行呢?當訪問量比較大的時候,最好是盡量減少session的數量比較好  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-28 23:12 bzp

          不用session來傳遞驗證碼,如何做?  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-29 11:49 零全零美

          不用session那也只能用cookie了,頁面展示的時候把驗證碼寫入cookie,并設置適當的有效期,提交的時候再驗證cookie里面的相應值!
          不過我感覺,如果不是訪問量大到離譜,用session存一下驗證碼也并沒有什么不妥!  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2009-11-29 22:39 星風

          一些小瑕疵:
          1.生成圖片時,傳入的寬度沒用上導致寬度過小時字符超出圖片寬度。
          // 寫驗證碼字符
          ...
          // fx += fsize * 0.9; // 原代碼
          // 根據傳入寬度調整字距并隨機±20%浮動
          fx += (width / textCode.length()) * (Math.random() * 0.4 + 0.8);
          ...

          2.VerifyCode.generateImageCode()的第二個重載無法拿到隨機生成的字符串,沒有任何意義。可以增加一個方法getLastTextCode()獲取但又必須保證線程安全,還不如刪掉。

          3.隨機顏色里
          Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
          應該是256

          4.生成驗證碼字符串的那一大段swich完全可以簡化,這樣太繁冗了。
          可以這樣寫(只是一個思路,沒有測試):
          // 添加一個靜態字段
          static char[] chars = {數字,大寫字母,小寫字母};
          ...
          // 方法內替換switch
          int begin = 0;
          int end = 0;
          switch (type) {
          case TYPE_NUM_ONLY:
          begin = 0;
          end = 10; // 第10個不是數字
          break;
          // 其他的case...
          }
          while (i < length) {
          int t = r.nextInt(end - begin); // 如果end設為9,這里要+1
          code.append(chars[t + begin]);
          i++;
          }
          ...


          最后感謝樓主的分享。  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載)[未登錄] 2009-11-30 10:29 IKnowIT

          @星風
          多謝您的意見,受教了。

          第1條:非常高明,我原來沒有考慮到,已經修改。多謝!
          具體浮動的數,上浮20%有時字符會超出邊界,測試一下可能:fx += (width / textCode.length()) * (Math.random() * 0.3 + 0.8); //0.4改為0.3更合適。

          第2條:原是想對外提供一個直接生成圖片的方法,但正如兄所說,如果用戶沒有textCode確實也沒用。已經去掉。

          第3條:應該是256,值包括255.

          第4條:有一定道理,只是當驗證碼是兩兩混合或者三者混合時,需要考慮到驗證碼的每個數都是從其中隨機抽取的,實際寫起來代碼量可能也不少。

          最后,非常感謝如星風兄此好的建議,受益匪淺。  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2010-09-26 10:03 來訪者

          謝謝  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2012-04-16 16:36 宋軍明

          多發點  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2014-05-05 21:14 zuidaima

          可以參考代碼:java隨機動態生成漢字驗證碼圖片的實例代碼分享,下載地址:http://www.zuidaima.com/share/1809721113234432.htm  回復  更多評論   

          # re: Java通用驗證碼程序及應用示例(提供源碼下載) 2014-07-14 15:03 劉鵬

          樓主,為什么我把代碼都復制了,驗證碼不顯示呢?顯示的是個x  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2009年11月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          最新評論

          主站蜘蛛池模板: 白水县| 德安县| 灯塔市| 商丘市| 克山县| 理塘县| 南投市| 苍山县| 安多县| 福海县| 收藏| 涿州市| 台东县| 托克托县| 南陵县| 平定县| 砚山县| 冷水江市| 阿坝县| 泗阳县| 黄龙县| 南昌县| 门源| 道孚县| 襄樊市| 贡山| 宜阳县| 屏边| 东乌珠穆沁旗| 重庆市| 离岛区| 滨州市| 大足县| 紫云| 运城市| 报价| 佛教| 拜城县| 黄龙县| 苍溪县| 凭祥市|