熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

驗證碼技術及其實現

2013-11-15 12:38:59  來源: PHP編程 

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

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

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

  #define counter_width
  #define counter_height
  static unsigned char counter_bits[] = {
    xcxxxxxxcxxxe
    };
  保存為 xbm 文件就可以得到一張顯示為 的圖片
  
  
  #define counter_width
  #define counter_height
  static unsigned char counter_bits[]={
  xcxcxcxcxcxxcxcxffxfexxxxxxxxxcxfexcxcxcxcxcxxxxxxcxcxcxcxcxcxxxxxcxcxcxcxcxexxxxexcxcxcxcxcxxxxxxcxcxcxcxcxcxcxcxxcxcxcxcxcxcxcxxxxcxxxxxxxxxxxexexexexexcxexexxc};
  保存為 xbm文件則顯示為


From:http://tw.wingwit.com/Article/program/PHP/201311/21348.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.