程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 驗證碼技術及其實現

驗證碼技術及其實現

編輯:關於PHP編程

    不少網站為了防止用戶利用機器人自動注冊、登錄、灌水,都采用了驗證碼技術。所謂驗證碼,就是將一串隨機產生的數字或符號,生成一幅圖片,圖片裡加上一些干擾象素(防止OCR),由用戶肉眼識別其中的驗證碼信息,輸入表單提交網站驗證,驗證成功後才能使用某項功能。
    PHP實現:
      我們這裡展示了如何編寫PHP程序實現驗證碼功能:
      
              代碼一: 
      
              <?php
              /*
              *  Filename:  authpage.php
              *  Author:  hutuworm
              *  Date:  2003-04-28
              *  @Copyleft  hutuworm.org
              */
      
              srand((double)microtime()*1000000);
      
              //驗證用戶輸入是否和驗證碼一致
                if(isset($HTTP_POST_VARS['authinput'])) 
                {
                    if(strcmp($HTTP_POST_VARS['authnum'],$HTTP_POST_VARS['authinput'])==0)
      
                        echo "驗證成功!";
                    else
                        echo "驗證失敗!";
                }
              
              //生成新的四位整數驗證碼
                while(($authnum=rand()%10000)<1000); 
              ?>
                <form action=authpage.php method=post>
                <table>
                    請輸入驗證碼:<input type=text name=authinput style="width:
            80px"><br>
                    <input type=submit name="驗證" value="提交驗證碼">
                    <input type=hidden name=authnum value=<? echo $authnum; ?>>
                    <img src=authimg.php?authnum=<? echo $authnum; ?>>
                </table>
                </form>
      
              代碼二:
      
            <?php
              /*
              *  Filename:  authimg.php
              *  Author:  hutuworm
              *  Date:  2003-04-28
              *  @Copyleft  hutuworm.org
              */
      
              //生成驗證碼圖片
                Header("Content-type: image/PNG"); 
                srand((double)microtime()*1000000);
                $im = imagecreate(58,28);
                $black = ImageColorAllocate($im, 0,0,0);
                $white = ImageColorAllocate($im, 255,255,255);
                $gray = ImageColorAllocate($im, 200,200,200);
                imagefill($im,68,30,$gray);
      
              //將四位整數驗證碼繪入圖片
                imagestring($im, 5, 10, 8, $HTTP_GET_VARS['authnum'], $black);
      
                for($i=0;$i<50;$i++)  //加入干擾象素
                {
                    imagesetpixel($im, rand()%70 , rand()%30 , $black);
                }
      
                ImagePNG($im);
                ImageDestroy($im);
              ?>
      
      
      
              本文程序在Apache 2.0.45 + PHP 4.3.1環境下運行通過。
      
            上文只是對驗證碼功能的一個簡單實現,並沒有考慮商用安全性問題。如果要增強安全性,將此功能投入商業應用,則可以通過以下幾個步驟實現:
      
            1. 啟用Session。
            2. authnum在authimg.php中生成,並計算md5sum,存入session。
            3.
      authpage.php將authinput計算md5sum後,與session中的authnum(md5sum)對比得出驗證結果。
      
      
            本站注:作者使用了簡單的代碼實現了很酷的功能。不過在添加干擾像素時的效果不是太好,大家可以看一下雨聲論壇登錄時的效驗碼(http://ror.cn/perl/ut/user_login.cgi),偶把第二段代碼稍改了一下,生成了與其類似的效果。
      
            修改後的代碼如下:
      
            <?php
            /*
            *  Filename: authimg.php
            *  Author:  hutuworm
            *  Date:   2003-04-28
            *  @Copyleft hutuworm.org
            */
            //生成驗證碼圖片
            Header("Content-type: image/PNG"); 
            srand((double)microtime()*1000000);
            $im = imagecreate(62,20);
            $black = ImageColorAllocate($im, 0,0,0);
            $white = ImageColorAllocate($im, 255,255,255);
            $gray = ImageColorAllocate($im, 200,200,200);
            imagefill($im,68,30,$gray);
            while(($authnum=rand()%100000)<10000);
            //將四位整數驗證碼繪入圖片
            imagestring($im, 5, 10, 3, $authnum, $black);
            for($i=0;$i<200;$i++)  //加入干擾象素
            {
              $randcolor =
            ImageColorallocate($im,rand(0,255),rand(0,255),rand(0,255));
              imagesetpixel($im, rand()%70 , rand()%30 , $randcolor);
            }
            ImagePNG($im);
            ImageDestroy($im);
            ?>
            顯示結果如下圖:
      [在新窗口中浏覽該圖片]

      有興趣的朋友可以自己試一下。

    看一下上面這段代碼:
      第一次看PHP代碼,呵呵。奇怪的學習經歷。
      
      
      代碼一: 
        
                <?php
                /*
                *  Filename:  authpage.php
                *  Author:  hutuworm
                *  Date:  2003-04-28
                *  @Copyleft  hutuworm.org
                */
      
      //以系統時間為種子得到隨機數
      //srand -- 播下隨機數發生器種子
      //microtime -- 返回當前 UNIX 時間戳和微秒數
      
                srand((double)microtime()*1000000);
        
                //驗證用戶輸入是否和驗證碼一致
                  if(isset($HTTP_POST_VARS['authinput'])) 
                  {
      //authnum的值是不應該發送到客戶端的,這裡應該是為了構建一個簡單的例子先吧
      //authnum 保存在 session 裡應該是個可行的辦法
      
                      if(strcmp($HTTP_POST_VARS['authnum'],$HTTP_POST_VARS['authinput'])==0)
        
                          echo "驗證成功!";
                      else
                          echo "驗證失敗!";
                  }
                
                //生成新的四位整數驗證碼
                  while(($authnum=rand()%10000)<1000); 
                ?>
                  <form action=authpage.php method=post>
                  <table>
                      請輸入驗證碼:<input type=text name=authinput style="width:
              80px"><br>
                      <input type=submit name="驗證" value="提交驗證碼">
                      <input type=hidden name=authnum value=<? echo $authnum; ?>>
                      <img src=authimg.php?authnum=<? echo $authnum; ?>>
                  </table>
                  </form>
        
                代碼二:
      
        
              <?php
                /*
                *  Filename:  authimg.php
                *  Author:  hutuworm
                *  Date:  2003-04-28
                *  @Copyleft  hutuworm.org
                */
      
      //下面幾行代碼肯定會讓寫ASP的GGDD們羨慕不已。
        
                //生成驗證碼圖片
      
      //指定頭信息
        
                  Header("Content-type: image/PNG"); 
                  srand((double)microtime()*1000000);
      
      //返回一個圖像標識符,代表了一幅大小為58 X 28的空白圖像。
                    $im = imagecreate(58,28);
                  $black = ImageColorAllocate($im, 0,0,0);
                  $white = ImageColorAllocate($im, 255,255,255);
                  $gray = ImageColorAllocate($im, 200,200,200);
                  imagefill($im,68,30,$gray);
      
      
      //強悍!!
      
       
                //將四位整數驗證碼繪入圖片
      
      //方便起見,使可以通過authimg.php?authnum=XXXX的方式得到圖片。實際應用中這種做法肯定是不足取的。
                
         imagestring($im, 5, 10, 8, $HTTP_GET_VARS['authnum'], $black);
        
                  for($i=0;$i<50;$i++)  //加入干擾象素
                  {
                      imagesetpixel($im, rand()%70 , rand()%30 , $black);
                  }
        
                  ImagePNG($im);
      //imagepng -- 以 PNG 格式將圖像輸出到浏覽器或文件
                  ImageDestroy($im);
                ?>
        
        
        
                本文程序在Apache 2.0.45 + PHP 4.3.1環境下運行通過。
        
              上文只是對驗證碼功能的一個簡單實現,並沒有考慮商用安全性問題。如果要增強安全性,將此功能投入商業應用,則可以通過以下幾個步驟實現:
        
              1. 啟用Session。
              2. authnum在authimg.php中生成,並計算md5sum,存入session。
              3. authpage.php將authinput計算md5sum後,與session中的authnum(md5sum)對比得出驗證結果。
        
        
              本站注:作者使用了簡單的代碼實現了很酷的功能。不過在添加干擾像素時的效果不是太好,大家可以看一下雨聲論壇登錄時的效驗碼(http://ror.cn/perl/ut/user_login.cgi),偶把第二段代碼稍改了一下,生成了與其類似的效果。
        
              修改後的代碼如下:
        
              <?php
              /*
              *  Filename: authimg.php
              *  Author:  hutuworm
              *  Date:   2003-04-28
              *  @Copyleft hutuworm.org
              */
              //生成驗證碼圖片
              Header("Content-type: image/PNG"); 
              srand((double)microtime()*1000000);
              $im = imagecreate(62,20);
              $black = ImageColorAllocate($im, 0,0,0);
              $white = ImageColorAllocate($im, 255,255,255);
              $gray = ImageColorAllocate($im, 200,200,200);
              imagefill($im,68,30,$gray);
              while(($authnum=rand()%100000)<10000);
              //將四位整數驗證碼繪入圖片
              imagestring($im, 5, 10, 3, $authnum, $black);
              for($i=0;$i<200;$i++)  //加入干擾象素
              {
                $randcolor =
              ImageColorallocate($im,rand(0,255),rand(0,255),rand(0,255));
                imagesetpixel($im, rand()%70 , rand()%30 , $randcolor);
              }
              ImagePNG($im);
              ImageDestroy($im);
              ?>
    驗證碼技術核心內容是動態生成圖片。ASP做到這一點,最簡單也是最普遍的就是用到XBM。我們先了解一下XBM的相關知識。
      
      
      [轉]用XBM創建動態客戶端圖像
      
      作者: BUILDER.COM
      Wednesday, April 9 2003 11:23 AM
      X-Bitmap(XBM)是一種古老但通用的圖像文件格式,它與現在的許多Web浏覽器都兼容。X-Windows圖形界面(UNIX和Linux常用的GUI)的C代碼庫xlib中有一個組件專門描述了它的規范。我將解釋XBM格式的工作原理,然後向你展示一種更有趣的使用它的方法:在客戶端創建動態圖像。文章中的代碼可以在此下載。
      
      XBM基礎
      
      XBM格式本來是為存儲單色的系統位圖而設計的,比如圖標和鼠標指針。XBM圖形的實質上是使用16進制數組來表示二進制圖像的C源代碼文件。(16進制數組表示的二進制圖像)
      
      這裡你也許會問:這種文件格式與Web浏覽器有什麼關系?在上世紀九十年代早期,美國超級計算應用中心(NCSA)在伊利諾斯大學開發第一個被廣泛使用的Web浏覽器,名為Mosaic。這個浏覽器的圖形支持來自很多開放源碼代碼庫,其中就包括xlib。因此,導致今天的許多浏覽器能夠處理XBM圖形。
      
      Mosaic項目後來成為了Netscape浏覽器的開發基礎。微軟也借用了一部分Mosaic代碼來創建Internet Explorer。微軟繼而在網絡信息服務器(IIS)中將XBM作為一個MIME類型注冊而提供本地支持,並且在現有所有版本的Internet Explorer中將其作為一種可支持的圖像。(浏覽器的廣泛支持)
      
      從一個程序員的角度來看,JPEG或GIF與XBM有著極大的不同。這兩種文件格式都在位級別上操作並使用了壓縮算法。它們可以支持很大的顏色深度范圍。創建這些動態Web圖形的唯一方法是使用服務器端的腳本,比如<a href=http://stein.cshl.org/WWW/software/GD/GD.pm和CGI/Perl腳本的結合,或者通過System.Drawing名字空間訪問ASP.NET中的圖形設計接口類庫(GDI+)。(升級到ASP.NET有很多個理由。)
      
      XBM創建起來很有程序性。每個位都被一一指定,而結果圖形被限制為兩色(黑色和白色)。(局限性之一:讓人不爽)X-Bitmap並不是必須服務器端腳本,可以在客戶端用JavaScript實時創建它們。(增加了不少靈活性)
      
      X-Bitmap的實用程序包括動態生成的圖、頁面計數器、老式圖形圖標、以及統計圖表。(就是通過位控制太麻煩了,有良好的包裝就好了。另外:生成圖片的大小,算法的強度,是否都達到了可用的要求?)給我印象最深的XMB應用是一個叫Wolfenstein 5k的游戲,它是一個紋理映射的第一視角射擊游戲,用JavaScript編寫,只有5KB大小。(不錯啊,稍後爽一下)
    通過使用IMG標識可以很容易地將XBM文件嵌入到一個Web頁面中。其語法如下:
      
      <img src=”xbmsmill.xbm”>
      
      ----------------------------------------------------------------------
      注意
      
      這種格式不對Mac或相應的浏覽器有效,比如Mozilla的早期版本。
      
      
      ----------------------------------------------------------------------
      典型的XBM源代碼與列表A中顯示的比較相像。
      
      #define語句以像素點為單位設置了圖像的寬度和高度。你也可以使用x_hot和y_hot命令來定義圖像中的一個熱點。我已經創建了一個X-Bitmap來描繪這個過程。為了設計它,我先將圖像映射為二進制值,如果你仔細的看,在這裡你會看到一張笑臉。
      
      我所創建的二進制圖像寬16個數字高7個數字,在我們的源代碼的XBM頭中定義了相同大小的寬/高像素值。圖像本身被存儲在一個靜態數組中,它包含一列二進制編碼的十六進制(BCH)值——換句話說,每四位分成一組。
      
      計算出笑臉的十六進制值得最簡單的方法是一次檢驗圖像的一行,將二進制值分成四位一組的分段,將每個分段映射成二進制/十六進制表中對應的十六進制數。下面是第一行:
      
      0001100001100000
      
      下面兩行分別表示四位的分段和其在表A中對應的十六進制數
      
      二進制: 0001  1000  0110  0000
      
      十六進制:  8   1   6   0
      
      表A
      
      XBM二/十六進制轉換表
      
      二進制 十六進制
      
      0000 0
      
      1000 1
      
      0100 2
      
      1100 3
      
      0010 4
      
      1010 5
      
      0110 6
      
      1110 7
      
      0001 8
      
      1001 9
      
      0101 A
      
      1101 B
      
      0011 C
      
      1011 D
      
      0111 E
      
      1111 F
      
      
      請注意這些並不是標准的二/十六進制轉換。它們是反向計算的(從左到右)而不是從右到左。把它顛倒是因為浏覽器會從左到右來讀圖形,我們的代碼必須與其一致。
      
      最後要把這些十六進制值轉換成XBM的右格式。必須在每個十六進制值前加“0x”。這是標准C++表示十六進制的方法。然後將這些值從右到左輸出(每個十六進制對表示八位二進制位)。請看列表B中的例子。
      
      因此,我們可以說:
      
      0001100001100000=0x18,0x06
      
      這些符合XBM的值可以很容易地插入到圖像數組中:
      
      static unsigned char xbmsmile_bits[]=
      
      現在我們來看看格式本身,現在是時候來學習在客戶端浏覽器中動態創建X-Bitmap了。
    圖片用點陣的形式表示,比如2:
      
      00111100 0011為3 1100為C 即0x3c
      01100110 0110為6 0110為6 0x66
      01100000 ....... 0x表示十六進制數。
      01100000 依此類推
      00110000 這是用二進制數得到的點陣,其中的1為顯示一黑點,0不顯示
      00011000 是一個反著看的2
      00001100 其余數字可自已排列點陣再二進制化為十六進制數
      00000110 缺點是只有黑白兩種顏色
      00000110 顯示出來是白底黑字,要顯示黑底白字的話,對其取反就行了
      01111110
      
      下面是我"畫"的0-9的數字
      
      num.asp
      
      <%
      Dim a(10,10)
      
      a(0,1) = "0x3c" '數字0
      a(0,2) = "0x66"
      a(0,3) = "0xc3"
      a(0,4) = "0xc3"
      a(0,5) = "0xc3"
      a(0,6) = "0xc3"
      a(0,7) = "0xc3"
      a(0,8) = "0xc3"
      a(0,9) = "0x66"
      a(0,10)= "0x3c"
      
      a(1,1) = "0x18" '數字1
      a(1,2) = "0x1c"
      a(1,3) = "0x18"
      a(1,4) = "0x18"
      a(1,5) = "0x18"
      a(1,6) = "0x18"
      a(1,7) = "0x18"
      a(1,8) = "0x18"
      a(1,9) = "0x18"
      a(0,10)= "0x7e"
      
      
      a(2,1) = "0x3c" '數字2
      a(2,2) = "0x66"
      a(2,3) = "0x60"
      a(2,4) = "0x60"
      a(2,5) = "0x30"
      a(2,6) = "0x18"
      a(2,7) = "0x0c"
      a(2,8) = "0x06"
      a(2,9) = "0x06"
      a(2,10)= "0x7e"
      
      a(3,1) = "0x3c" '數字3
      a(3,2) = "0x66"
      a(3,3) = "0xc0"
      a(3,4) = "0x60"
      a(3,5) = "0x1c"
      a(3,6) = "0x60"
      a(3,7) = "0xc0"
      a(3,8) = "0xc0"
      a(3,9) = "0x66"
      a(3,10)= "0x38"
      
      a(4,1) = "0x38" '數字4
      a(4,2) = "0x3c"
      a(4,3) = "0x36"
      a(4,4) = "0x33"
      a(4,5) = "0x33"
      a(4,6) = "0x33"
      a(4,7) = "0xff"
      a(4,8) = "0x30"
      a(4,9) = "0x30"
      a(4,10)= "0xfe"
      
      a(5,1) = "0xfe" '數字5
      a(5,2) = "0xfe"
      a(5,3) = "0x06"
      a(5,4) = "0x06"
      a(5,5) = "0x3e"
      a(5,6) = "0x60"
      a(5,7) = "0xc0"
      a(5,8) = "0xc3"
      a(5,9) = "0x66"
      a(5,10)= "0x3c"
      
      a(6,1) = "0x60" '數字6
      a(6,2) = "0x30"
      a(6,3) = "0x18"
      a(6,4) = "0x0c"
      a(6,5) = "0x3e"
      a(6,6) = "0x63"
      a(6,7) = "0xc3"
      a(6,8) = "0xc3"
      a(6,9) = "0x66"
      a(6,10) ="0x3c"
      
      a(7,1) = "0xff" '數字7
      a(7,2) = "0xc0"
      a(7,3) = "0x60"
      a(7,4) = "0x30"
      a(7,5) = "0x18"
      a(7,6) = "0x18"
      a(7,7) = "0x18"
      a(7,8) = "0x18"
      a(7,9) = "0x18"
      a(7,10)= "0x18"
      
      a(8,1) = "0x3c" '數字8
      a(8,2) = "0x66"
      a(8,3) = "0xc3"
      a(8,4) = "0x66"
      a(8,5) = "0x3c"
      a(8,6) = "0x66"
      a(8,7) = "0xc3"
      a(8,8) = "0xc3"
      a(8,9) = "0x66"
      a(8,10)= "0x3c"
      
      a(9,1) = "0x3c" '數字9
      a(9,2) = "0x66"
      a(9,3) = "0xc3"
      a(9,4) = "0xc3"
      a(9,5) = "0x66"
      a(9,6) = "0x3c"
      a(9,7) = "0x18"
      a(9,8) = "0x0c"
      a(9,9) = "0x06"
      a(9,10)= "0x03"
      
      %>
      
      顯示的方法是:
      
      1.先傳出一個MIME:
      Response.ContentType = "image/x-xbitmap"
      2.再傳出一個c++的源程序,如顯示2:
      #define counter_width 8
      #define counter_height 10
      static unsigned char counter_bits[] = {
      0x3c,0x66,0x60,0x60,0x30,0x18,0x0c,0x06,0x06,0x7e
      };
      這樣在浏覽器上就顯示出來一個8*10像素的2了
      
      要顯示兩個或以上的數字的時候,須改動寬度的值(必須是圖像點陣寬度的整數倍),在count_bits[]數組的值排序如下:
      比如顯示 12
      a(1,1), a(2,1), a(1,2), a(2,2)... a(1,10), a(2,10)
      下面是具體計數器的例子:
      
      count.asp
      
      <!--#include file="num.asp"-->
      <%
      Dim Image
      Dim Width, Height
      Dim num
      Dim digtal
      Dim Length
      Dim sort
      Length = 10 '自定計數器長度
      
      Redim sort( Length )
      
      
      num = 62275 '計數器的值
      digital = ""
      For I = 1 To Length -Len( num ) '補0
      digital = digital & "0"
      Next
      For I = 1 To Len( num )
      digital = digital & Mid( num, I, 1 )
      Next
      For I = 1 To Len( digital )
      sort(I) = Mid( digital, I, 1 )
      Next
      Width = 8 * Len( digital ) '圖像的寬度
      Height = 10 '圖像的高度,在本例中為固定值
      
      
      Response.ContentType="image/x-xbitmap"
      
      hc=chr(13) & chr(10)
      
      Image = "#define counter_width " & Width & hc
      Image = Image & "#define counter_height " & Height & hc
      Image = Image & "static unsigned char counter_bits[]={" & hc
      
      For I = 1 To Height
      For J = 1 To Length
      Image = Image & a(sort(J),I) & ","
      Next
      Next
      
      Image = Left( Image, Len( Image ) - 1 ) '去掉最後一個逗號
      Image = Image & "};" & hc
      
      Response.Write Image
      
      %>

      #define counter_width 8
      #define counter_height 10
      static unsigned char counter_bits[] = {
        0x3c,0x66,0x60,0x60,0x30,0x18,0x0c,0x06,0x06,0x7e
        };
      保存為 xbm 文件就可以得到一張顯示為 2 的圖片
      
      
      #define counter_width 80
      #define counter_height 10
      static unsigned char counter_bits[]={
      0x3c,0x3c,0x3c,0x3c,0x3c,0x60,0x3c,0x3c,0xff,0xfe,0x66,0x66,0x66,0x66,0x66,0x30,0x66,0x66,0xc0,0xfe,0xc3,0xc3,0xc3,0xc3,0xc3,0x18,0x60,0x60,0x60,0x06,0xc3,0xc3,0xc3,0xc3,0xc3,0x0c,0x60,0x60,0x30,0x06,0xc3,0xc3,0xc3,0xc3,0xc3,0x3e,0x30,0x30,0x18,0x3e,0xc3,0xc3,0xc3,0xc3,0xc3,0x63,0x18,0x18,0x18,0x60,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x0c,0x0c,0x18,0xc0,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x06,0x06,0x18,0xc3,0x66,0x66,0x66,0x66,0x66,0x66,0x06,0x06,0x18,0x66,0x7e,0x7e,0x7e,0x7e,0x7e,0x3c,0x7e,0x7e,0x18,0x3c};
      保存為 xbm文件則顯示為 0000062275 。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved