千里冰封
          JAVA 濃香四溢
          posts - 151,comments - 2801,trackbacks - 0

          有時(shí)候在我們的網(wǎng)絡(luò)應(yīng)用中,防止程序自動(dòng)登錄搞破壞,我們一般都會(huì)加上驗(yàn)證碼,這些驗(yàn)證碼一般來(lái)說(shuō)都是由人來(lái)識(shí)別的,當(dāng)然,如果驗(yàn)證碼很有規(guī)律,或者說(shuō)很清楚,漂亮,那么也是可能被程序識(shí)別的,我以前就識(shí)別過(guò)某網(wǎng)站的驗(yàn)證碼,因?yàn)楸容^有規(guī)律,所以被識(shí)別了,并且識(shí)別率達(dá)到99%左右,其實(shí)我們可以制作很復(fù)雜一點(diǎn)的驗(yàn)證碼,添加一些干擾的線條或者字體變形,使程序識(shí)別的難度加大,這樣,我們的目的也就達(dá)到了.

          下面是生成的圖片:


          代碼如下,JSP代碼

          <%@page contentType="image/jpeg"%>
          <%@page pageEncoding="UTF-8"%>
          <%@ page import="java.awt.*,javax.imageio.*,java.io.*,java.util.*,java.awt.image.*" %>
          <%--
          The taglib directive below imports the JSTL library. If you uncomment it,
          you must also add the JSTL library to the project. The Add Library action
          on Libraries node in Projects view can be used to add the JSTL 
          1.1 library.
          --%>
          <%--
          <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
          --%>

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
          "http://www.w3.org/TR/html4/loose.dtd">
          <%!String s="";%>
          <%
          java.util.List
          <String> fonts=new ArrayList<String>();
          GraphicsEnvironment.getLocalGraphicsEnvironment().preferLocaleFonts();
          String[] names
          =GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.CHINA);
          for(String s:names){
              
          char c=s.charAt(0);
              
          if(Character.isLowerCase(c)||Character.isUpperCase(c)){
                  
              }
          else{
                  fonts.add(s);
              }
          }
          BufferedImage bi
          =new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
          Graphics2D g
          =bi.createGraphics();
          char[] cs={'0','1','2','3','4','5','6','7','8','9'};
          char[] use=new char[4];
          g.setColor(
          new Color(240,240,240));
          g.fillRect(
          0,0,200,50);
          for(int i=0;i<4;i++){
              Point p
          =new Point(5+(i*((int)(Math.random()*10)+40)),40);
              
          int size=0;
              
          int[] sizes=new int[20];
              
          for(int j=0;j<20;j++){
                  sizes[j]
          =30+j;
              }
              size
          =sizes[(int)(Math.random()*sizes.length)];
              
          int face=0;
              
          if(Math.random()*10>5){
                  face
          =Font.BOLD;
              }
          else{
                  face
          =Font.ITALIC;
              }
              use[i]
          =cs[(int)(Math.random()*cs.length)];
              g.setPaint(
          new GradientPaint(p.x,p.y,new Color((int)(Math.random()*256),0,(int)(Math.random()*256)),
                      p.x,p.y
          -size,new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256))));
              g.setFont(
          new Font(fonts.get((int)(Math.random()*fonts.size())),face,size));
              g.drawString(
          ""+use[i],p.x,p.y);
          }
          s
          =new String(use);
          session.setAttribute(
          "code", s);
          g.setPaint(
          null);
          for(int i=0;i<4;i++){
              g.setColor(
          new Color((int)(Math.random()*0x00FFFFFFF)));
              g.drawLine((
          int)(Math.random()*200),(int)(Math.random()*50),(int)(Math.random()*200),(int)(Math.random()*50));
          }
          Random random 
          = new Random();
          for (int i=0;i<88;i++) {
              
          int x = random.nextInt(200);
              
          int y = random.nextInt(50);
              g.setColor(
          new Color((int)(Math.random()*0x00FFFFFFF)));
              g.setStroke(
          new BasicStroke((float)(Math.random()*3)));
              g.drawLine(x,y,x,y);
          }
          OutputStream ot
          =response.getOutputStream();
          ImageIO.write(bi,
          "JPEG",ot);
          g.dispose();
          ot.close();
          %>

          以下是Servlet代碼
          /*
           * Code.java
           *
           * Created on 2007年9月21日, 下午12:08
           
          */

          package com.hadeslee;

          import java.awt.BasicStroke;
          import java.awt.Color;
          import java.awt.Font;
          import java.awt.GradientPaint;
          import java.awt.Graphics2D;
          import java.awt.GraphicsEnvironment;
          import java.awt.Paint;
          import java.awt.Point;
          import java.awt.Stroke;
          import java.awt.image.BufferedImage;
          import java.io.*;
          import java.util.ArrayList;
          import java.util.List;
          import java.util.Locale;
          import java.util.Random;
          import javax.imageio.ImageIO;

          import javax.servlet.*;
          import javax.servlet.http.*;

          /**
           *
           * 
          @author lbf
           * 
          @version
           
          */
          public class Code extends HttpServlet {
              
              
          /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
               * 
          @param request servlet request
               * 
          @param response servlet response
               
          */
              
          private List<String> fonts=new ArrayList<String>();
              
          public Code(){
                  initFonts();
              }
              
          private void initFonts(){
                  GraphicsEnvironment.getLocalGraphicsEnvironment().preferLocaleFonts();
                  String[] names
          =GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.CHINA);
                  
          for(String s:names){
                      
          char c=s.charAt(0);
                      
          if(Character.isLowerCase(c)||Character.isUpperCase(c)){
                          
                      }
          else{
                          fonts.add(s);
                      }
                  }
              }
              
          protected void processRequest(HttpServletRequest request, HttpServletResponse response)
              
          throws ServletException, IOException {
                  response.setContentType(
          "image/jpeg;charset=UTF-8");
                  OutputStream out
          =response.getOutputStream();
                  BufferedImage bi
          =new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
                  Graphics2D g
          =bi.createGraphics();
                  
          char[] cs={'0','1','2','3','4','5','6','7','8','9'};
                  
          char[] use=new char[4];
                  g.setColor(
          new Color(240,240,240));
                  g.fillRect(
          0,0,200,50);
                  
          for(int i=0;i<4;i++){
                      Point p
          =getPoint(i);
                      
          int size=getSize();
                      use[i]
          =cs[(int)(Math.random()*cs.length)];
                     
          // g.setColor(new Color((int)(Math.random()*256),0,(int)(Math.random()*256)));
                      g.setPaint(getPaint(p,size));
                      g.setFont(
          new Font(fonts.get((int)(Math.random()*fonts.size())),getFace(),size));
                      g.drawString(
          ""+use[i],p.x,p.y);
                  }
                  g.setStroke(
          new BasicStroke(1.0f));
                  g.setPaint(
          null);
                  
          for(int i=0;i<4;i++){
                      g.setColor(
          new Color((int)(Math.random()*0x00FFFFFFF)));
                      g.drawLine((
          int)(Math.random()*200),(int)(Math.random()*50),(int)(Math.random()*200),(int)(Math.random()*50));
                  }
                  Random random 
          = new Random();
                  
          for (int i=0;i<88;i++) {
                      
          int x = random.nextInt(200);
                      
          int y = random.nextInt(50);
                      g.setColor(
          new Color((int)(Math.random()*0x00FFFFFFF)));
                      g.setStroke(getStroke());
                      g.drawLine(x,y,x,y);
                  }
                  ImageIO.write(bi,
          "JPEG",out);
                  out.close();
                  g.dispose();
              }
              
          private Stroke getStroke(){
                BasicStroke bs
          =new BasicStroke((float)(Math.random()*3));
                
          return bs;
              }
              
          private Point getPoint(int index){
                  
          return new Point(5+(index*((int)(Math.random()*10)+40)),40);
              }
              
          private Paint getPaint(Point p,int size){
                  GradientPaint gp
          =new GradientPaint(p.x,p.y,new Color((int)(Math.random()*256),0,(int)(Math.random()*256)),
                          p.x,p.y
          -size,new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256)));
                  
          return gp;
              }
              
          private int getFace(){
                  
          if(Math.random()*10>5){
                      
          return Font.BOLD;
                  }
          else{
                      
          return Font.ITALIC;
                  }
              }
              
          private int getSize(){
                  
          int[] sizes=new int[20];
                  
          for(int i=0;i<20;i++){
                      sizes[i]
          =30+i;
                  }
                  
          return sizes[(int)(Math.random()*sizes.length)];
              }
              
              
          // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
              /** Handles the HTTP <code>GET</code> method.
               * 
          @param request servlet request
               * 
          @param response servlet response
               
          */
              
          protected void doGet(HttpServletRequest request, HttpServletResponse response)
              
          throws ServletException, IOException {
                  processRequest(request, response);
              }
              
              
          /** Handles the HTTP <code>POST</code> method.
               * 
          @param request servlet request
               * 
          @param response servlet response
               
          */
              
          protected void doPost(HttpServletRequest request, HttpServletResponse response)
              
          throws ServletException, IOException {
                  processRequest(request, response);
              }
              
              
          /** Returns a short description of the servlet.
               
          */
              
          public String getServletInfo() {
                  
          return "Short description";
              }
              
          // </editor-fold>
          }


          在這里我們先得到了服務(wù)器所在的系統(tǒng)的字體,并用這些字體生成不同的字符,然后再隨機(jī)設(shè)大小,隨機(jī)變形,然后為字體加上漸變,并給整個(gè)圖片添加干擾線條以及干擾點(diǎn).讓程序識(shí)別的難度加大.

          呵呵,我們可以把它改成字母或者中文的驗(yàn)證,道理都是一樣的,只不過(guò)在生成的時(shí)候,不一定用數(shù)字了,而是用所有可以輸入的文字.這樣,被程序識(shí)別的可能又小了.


          盡管千里冰封
          依然擁有晴空

          你我共同品味JAVA的濃香.
          posted on 2007-09-21 13:05 千里冰封 閱讀(2237) 評(píng)論(10)  編輯  收藏 所屬分類(lèi): JAVAEE

          FeedBack:
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-21 14:06 | sitinspring
          作個(gè)記號(hào),用到時(shí)再來(lái)細(xì)看.  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-21 16:06 | zht
          還有另外一種方式是根據(jù)隨機(jī)數(shù)從服務(wù)器上取圖片然后再畫(huà)出來(lái),
          感覺(jué)這樣數(shù)字的風(fēng)格可以隨時(shí)換  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成[未登錄](méi)
          2007-09-21 17:00 | a
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成[未登錄](méi)
          2007-09-22 09:26 | quaff
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-22 21:45 | cocobear
          可不可以寫(xiě)一個(gè)識(shí)別你這個(gè)驗(yàn)證碼的程序呢?呵呵  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-23 14:14 | Alexander.Yu
          不錯(cuò)...強(qiáng)啊.  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-27 17:16 | 彭俊
          我也想聽(tīng)聽(tīng)你關(guān)于如何識(shí)別驗(yàn)證碼的基本思路,沒(méi)有干擾也好。請(qǐng)教要如何識(shí)別呢?  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-27 17:27 | 千里冰封
          @彭俊
          最基本的思路就是比對(duì),先提取出來(lái)字模,然后再比對(duì)就可以了  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-27 17:37 | 彭俊
          @千里冰封
          抽點(diǎn)時(shí)間寫(xiě)寫(xiě)這個(gè)內(nèi)容吧 呵呵
          這方面接觸的比較少 簡(jiǎn)單的說(shuō)一下沒(méi)有感覺(jué)啊
          來(lái)點(diǎn)直接的Code,肯定有不少人期待呢
          當(dāng)然我也會(huì)取search一下先做做功課的
          先謝謝了  回復(fù)  更多評(píng)論
            
          # re: 隨機(jī)數(shù)字驗(yàn)證碼的生成
          2007-09-27 17:47 | 千里冰封
          @彭俊
          呵呵,好吧,我就把去年寫(xiě)的拿出來(lái)分享一下  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 绥化市| 福海县| 大方县| 凌云县| 古田县| 邹城市| 瑞丽市| 固阳县| 依安县| 灵寿县| 锡林郭勒盟| 哈巴河县| 陈巴尔虎旗| 青冈县| 武川县| 湟源县| 汉源县| 澄江县| 秭归县| 哈尔滨市| 吉林市| 和硕县| 南丰县| 阿克| 永顺县| 清徐县| 柳江县| 塘沽区| 临邑县| 渭南市| 辽中县| 海阳市| 织金县| 镇原县| 佛学| 和顺县| 历史| 承德市| 普兰店市| 阳泉市| 枣强县|