驗證碼開發過程中的 3 個誤區:
1、 背景幹擾:幹擾線、幹擾點、幹擾圖,基本沒有,程式很容易通過高亮度調節去除掉。
2、 字元旋轉:破解機器人通過數次學習、旋轉之後,能夠得到 90% 以上的正确識别率,采用正常字型,能夠得到接近 100% 的識别。
3、 随機間距:基本沒用,采用提取高亮度之後,采用圖檔切割的方法,很容易就将随機間距消滅掉。
防止被破解:
1、 背景幹擾線盡量能夠幹擾到字元,采用和字元相同的顔色,能夠破壞高亮度反差色提取法對字元的學習。 qq有采用。
2、 矢量變形:想 google 、 ms 、 yahoo 都采用了這種變态的方法,這種将字元進行扭曲變形,基本上機器識别率為零,因為沒有相對應的固定形狀。 損失是使用者也不一定認得。需要驗證碼圖檔有一些大才行。
3、 字元粘連,可以破壞掉字元切割法分割字元, google 也有用到這個, qq 也有采用。
4、 中文驗證碼,中文驗證碼的識别難度比較大,但是現在逐漸的也慢慢被學習并且破解。(香港,台灣是用繁體)
5、 字元旋轉:需要和字元粘連在一起才能夠起作用,他們一起,驗證碼幾乎不具備機器破解可能性。 加随機背景圖檔、随機字型、稍微旋轉字母或數字,位置不固定,稍微扭曲
注意:下載下傳空心字型
字型.ttf的當$mode=7的該字型必須支援中文,否則出現亂碼。
在服務端做驗證時取session存儲的驗證字元與使用者送出的字元進行比較,相同則通過驗證。

<?php
/*
* @date 2011-2-24
* @author hudeyong926
*/
function getcode($length = 32, $mode = 0) {
switch ($mode) {
case '1' :
$str = '123456789';
break;
case '2' :
$str = 'abcdefghijklmnopqrstuvwxyz';
case '3' :
case '4' :
$str = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz';
case '5' :
$str = 'abcdefghijklmnpqrstuvwxyz123456789';
case '6' :
$str = 'abcdefghijklmnopqrstuvwxyz1234567890';
case '7' ://中文驗證碼
default :
$str = 'abcdefghijklmnpqrstuvwxyzabcdefghijkmnpqrstuvwxyz23456789';
}
$result = '';
for($i = 0; $i < $length; $i ++) {
if ($mode == 7) {
$str [$i] = chr ( mt_rand ( 176, 215 ) ) . chr ( mt_rand ( 161, 249 ) );
$str [$i] = iconv ( "gb2312", "utf-8", $str [$i] ); //imagettftext是utf-8的,是以先轉換下
$result .= $str [$i];
} else {
$l = strlen ( $str ) - 1;
$num = mt_rand ( 0, $l );
$result .= $str [$num];
}
return $result;
}
//建立驗證圖檔
function createauthnumimg($randstr, $fontname, $imgw = 100, $imgh = 40) {
header ( "content-type: image/png" );
$image = imagecreate ( $imgw, $imgh );
$fontsize = 20;//字号
//$green = imagecolorallocate($image,0x6b,0xc1,0x46);
$gray = imagecolorallocate ( $image, 228, 228, 228 ); //灰色
$red = imagecolorallocate ( $image, 255, 102, 204 );//粉色
$blue = imagecolorallocate($image,0x53,0x68,0xbd);
$colors = array($red, $gray, $blue);
$color_b = imagecolorallocate ( $image, 0, 0, 0 ); //黑色
for($i = 0; $i < 1000; $i ++) { //繪背景幹擾點
imagesetpixel ( $image, mt_rand ( 0, $imgw ), mt_rand ( 0, $imgh ), $colors[rand(0,count($colors)-1)]);
imagerectangle ( $image, 0, 0, $imgw - 1, $imgh - 1, $color_b );//繪制邊框
imagettftext ( $image, $fontsize, 5, 3, 25, $color_b, $fontname, $randstr);///将驗證字元繪入圖檔 字元旋轉
for($i=0; $i<2; $i++){ //繪背景幹擾線
imageline($image, mt_rand(0,5), mt_rand(6,18), mt_rand(65,$imgw), mt_rand(6,$imgh), $color_b);//一條幹擾線
}
imagepng ( $image );
imagedestroy ( $image );
session_start ();
$verifycode = getcode ( 5 );
$_session ['verify_code'] = $verifycode ;
createauthnumimg ( $verifycode, "font.ttf", 75, 30); //字型存放路徑,如果你沒有檔案就去c:\windows\fonts檔案中找一個吧。
/** 問答模式
$a=getcode(2,1);
$b=getcode(1,1);
$passport = $a."+".$b."=?";
$verifycode = $a+$b;
$_session ['verify_code'] = $verifycode ;
createauthnumimg ( $passport, "font.ttf", 75, 30);
?>
中文占兩個字元長度,需要控制驗證碼圖檔的長度,一個中文位置相當于2個非中文

<?php echo strlen('中'); echo strlen('ad');?>
為了避免機器人的破解,驗證碼的視覺效果越來越差,随之很多網站就加了“看不清?請重新整理”之類的功能,當然也不是簡簡單單的頁面重新整理,是隻重新整理驗證碼部分,使用者進而得到一個新的驗證碼。在網上看了些别人寫的方法,下面總結兩種。
第一種比較簡單,運用一下onclick即可,直接點選驗證碼的圖檔就可以重新整理,不過最好在驗證碼後面說明一下,提示有這個功能。

<img src="validimg.jsp" alt="看不清?請重新整理" width="50" height="20" onclick="this.src=this.src+'?'+math.random()" />

<img src="validimg.jsp" width="50" height="20" > <a href="javascript:reloadimage("validimg.jsp" );">重新整理</a>
<script language="javascript">
function reloadimage(url){
document.formname.img1.src = url+math.random();
</script>