نوشتن کد PHP تولید کننده تصاویر امنیتی CAPTCHA
خوب در اینجا ما به سه فایل برای تولید CAPTCHA نیاز داریم:
- captcha_config.php
- captcha_code.php
- captcha_lib.php
همچنین ما به تعدادی فونت TrueType و همچنین تعدادی عکس برای background نیاز داریم که به ترتیب در فولدر های fonts و backgrounds قرار می گیرند. (این دو فولدر پیوست شده اند.)
خوب حالا می رویم سراغ کد نویسی...

ابتدا اجازه دهید فایل index.php را آماده کنیم:
کد HTML:
Error!
"; } else { echo "OK!
"; } } ?> "text/html; charset=utf-8">TEST CAPTCHA Test CAPTCHA Form action=""> >Name: "text" name="fullname" id="fullname" class="txt" /> >Message: cols="20" name="message" class="txt" > >Code: "text" name="code" id="Turing" class="txt" /> "captchac_code.php" id="captcha">
"/images/arrow_refresh.png" onclick="document.getElementById('captcha').src = document.getElementById('captcha').src + '?' + (new Date()).getMilliseconds()" align="right"> "submit" name="submit" value="Submit" class="btn" />
کد HTML:
"/images/arrow_refresh.png" onclick="document.getElementById('captcha').src = document.getElementById('captcha').src + '?' + (new Date()).getMilliseconds()" align="right">
خوب حالا بریم سراغ تکمیل اولین فایل، یعنی فایل Config. کد زیر را در فایل captcha_config.php وارد کنید:
کد PHP:
$CSize = 0;$CSizeWidth = 164; $CSizeHeight = 50;$CMinSize = 5; $CMaxSize = 6;$CBackgroundType = 0;$CBackgroundFile = 'backgrounds/1.gif';$CBackgroundFillType = 1;$CFontUsed = 1; $CFontURL = 'fonts/font30.ttf'; $FontNo = 34; $fonts_dir = 'fonts';$CFontColorType = 1;$color_text_r = 10; $color_text_g = 38; $color_text_b = 140; $CFontSizeMin = 25;$CFontSizeMax = 30;$CFontSizeMin = 25;$CFontSizeMax = 30;$CFontRotMin = -15;$CFontRotMax = 15;$CFontPadding = 2;# $output_type='jpeg';
# $output_type='gif';$output_type='png';$captcha_type = 1;

تنظیمات پس زمینه
خوب، برای متغیر CSize دو مقدار در نظر میگیریم: 0 و 1 . 0 برای حالتی که اندازه تصویر رو خودمون تعیین کنیم و 1 برای حالتی که برنامه خودش بصورت تصادفی (random) یه اندازه برای تصویر انتخاب کنه. در صورتیکه این مقدار صفر باشد، باید اندازه تصویر رو توسط متغیر های CSizeWidth و CSizeHeight بصورت دستی تعیین کنیم (واحد px).
CMinSize و CMaxSize نیز برای تعیین حداقل و حداکثر طول تصویر استفاده می شوند (برنامه بطور تصادفی تعداد کاراکترها را انتخاب می کند).
برای CBackgroundType نیز دو مقدار 0 و 1 در نظر می گیریم: 0 برای اینکه تصویر بصورت تصادفی و توسط خود PHP ساخته شود و 1 برای اینکه از تصاویر موجود در پوشه backgrounds استفاده شود. اگر مقدار آن را 1 تعیین کنید، برنامه از پس زمینه ای که آدرس آن را در متغیر CBackgroundFile تعیین کرده اید (فایلی از نوع GIF یا PNG یا JPEG)، استفاده خواهد کرد.
* هک : همچنین شما می توانید با کمی تغییر در این قسمت، و بطور تصادفی یکی از این حالات را تعیین و همچنین بطور تصادفی یکی از چند تصویر موجود در پوشه backgrounds را انتخاب کنید. (همگی توسط تابع mt_rand خود PHP) همانند کد زیر:
کد:
$rand1 = mt_rand(0,1);
$CBackgroundType = $rand1;
if($rand1==0) { $rand2 = mt_rand(1,24); }
$CBackgroundFile = 'images/cbg/'.$rand2.'.gif';
تنظیمات فونت
CFontUsed تعیین می کند که فونت بصورت تصادفی از پوشه fonts انتخاب شود (مقدار 1) یا اینکه از یک فونت مشخص استفاده کند (مقدار 0). در صورتیکه مقدار آن 0 باشد، باید با مقدار دهی CFontURL آدرس فونت مورد نظر را تعیین کنید.
متغیر FontNo هم تعداد فونت های موجود در پوشه fonts را تعیین می کند. اسامی فونت های موجود در پوشه بصورت fontx.ttf هستند که به جای x شماره فونت قرار میگیرد (در اینجا ما 34 فونت داریم که از font1.ttf تا font34.ttf شماره گذاری شده اند).
متغیر fonts_dir نیز نام (آدرس) پوشه فونت ها را نگه داری می کند.
متغیر CFontColorType چهار مقدار می پذیرد: 1 برای اینکه رنگ کاراکترها بصورت تصادفی انتخاب شود، 2 برای اینکه رنگ کاراکترها سیاه باشد، 3 به منظور سفید بودن کاراکترها و 4 هم برای انتخاب رنگ آن ها بصورت دستی. در صورتیکه گزینه 4 انتخاب شود، باید رنگ مورد نظر را بصورت RGB به متغیرهای color_text_r و color_text_g و color_text_b بدهید.
متغیرهای CFontSizeMin و CFontSizeMax به ترتیب حداقل و حداکثر اندازه فونت کاراکترها را نگه داری می کنند و برنامه بصورت تصادفی یک مقدار بین این دو عدد را به کاراکتر ها نسبت می دهد.
* هک : می توان ترتیبی اتخاذ کرد که هر کاراکتر از تصویر اندازه مجزایی داشته باشد (البته بصورت random) ... این تغییر را باید در فایل code و با کمی دستکاری در قسمت درج کد در تصویر انجام دهیم.
متغیرهای CFontRotMin و CFontRotMax نیز حداقل و حداکثر مقداری را که هر کاراکتر می تواند بچرخد، تعیین می کنند. (واحد درجه)
+ نکته : چرخش از راست به چپ صورت میگیرد. یعنی اگر بالفرض چرخش 90 درجه باشد، و حرف A چرخیده باشد، بالای آن در سمت چپ تصویر و پایین آن در سمت راست آن قرار خواهد گرفت. ضمن اینکه چرخش 15- درجه همانند چرخش 345 درجه عمل می کند و با لحن ساده می توان گفت که 15 درجه از چپ به راست چرخیده است.
متغیر CFontPadding مقدار فضای خالی اطراف هر کاراکتر را مشخص می کند. در صورت منفی بودن مقدار آن، ممکن است برخی از کاراکتر ها روی هم بیفتند. (ممکن است چون مکان خود هر کاراکتر در تصویر مشخص نیست، ولی اگر آن دو در جایی قرار بگیرند که نزدیک هم باشند، با توجه به اینکه فضای خالی اطرافشان منفی است، روی هم می افتند. در صورتیکه صفر یا مثبت می بود، به هیچ وجه این اتفاق نمی افتاد.)
متغیر output_type نیز نوع فایل تصویر خروجی را نگه داری می کند. این مقدار می تواند PNG یا JPEG باشد.
تنظیمات کلی
و در نهایت متغیر captcha_type نیز نوع CAPTCHA را مشخص می کند. (ممکن است شما بخواهید از روش های متفاوتی برای تولید تصاویر استفاده کنید، مخصوصا در حالتی که background رو با خود PHP میسازیم، این کار به چند طریق ممکنه و میشه از انواع گوناگون bg استفاده کرد. مثل پست اول همین تاپیک که bg بصورت خط خطی بود و ...)
خوب حالا می رویم سراغ فایل lib...
این فایل وظیفه دارد برای هر کاربر یک Session اختصاص دهد و نیز یک کد
تصادفی برای CAPTCHA تولید کند. همچنین چک کردن صحت ورود کد توسط کاربر
نیز در این فایل انجام میگیرد. همانطور که قبلا مشاهده کردید، این فایل به
صفحه اصلی فرم include می شود. خوب، اینم کد فایل captcha_lib.phpا:کد PHP:
session_start();
function RandomCode($min,$max)
{$src = 'abcdefghijkmnpqrstuvwxyz';$src .= '23456789';$srclen = strlen($src)-1;$length = mt_rand($min,$max);$Code = '';
for($i=0; $i<$length; $i++)
$Code .= substr($src, mt_rand(0, $srclen), 1);
return $Code;
}
function CheckCaptcha($Turing)
{
global $ImageCode;
if ( !isset( $_SESSION['turing_string'] ) ) { $ImageCode = ''; return 1; }
else if ( strtoupper($_SESSION['turing_string']) == strtoupper($Turing) ) { $ImageCode = 'ok'; return 1; }
else { $ImageCode = 'wrong'; return 0; }
}?>
در تابع RandomCode، متغیر src کاراکترهایی را که قرار است برای تولید کد از آن ها استفاده شود، در خود ذخیره می کند. متغیر srclen نیز طول این رشته را نگه داری می کند. متغیر length نیز بین حداقل و حداکثر کاراکتر های تعیین شده، تعداد تصادفی آن را به دست آورده و در خود ذخیره می کند. سپس برنامه با استفاده از یک حلقه for به تعداد تعیین شده، کاراکتر تصادفی تولید می کند و آن ها را بصورت یک رشته پشت سر هم در متغیر Code ذخیره می کند. و در نهایت مقدار این متغیر برگردانده می شود.
(پرانتز : توجه داشته باشید که فایل captcha_code.php فایل های captchac_config.php (برای مقادیر متغیرهای پیکربندی) و captchac_lib.php (برای استفاده از تابع RandomCode) را در خود include می کند.)
(پرانتز : در پست بعدی خواهید دید که فایل captcha_code.php که در واقع با ورود کاربر به صفحه فرم و توسط تگ img اجرا می شود، یک session به نام turing_string حاوی کد تولید شده، را ذخیره می کند. بعدها این کد توسط تابع CheckCaptcha موجود در فایل captcha_lib.php مورد استفاده قرار میگیرد.)
در تابع CheckCaptcha (که توسط صفحه حاوی فرم و پس از ارسال فرم فراخوانی شده بود) نیز، در صورتیکه session اِ turing_string تعریف شده باشد، مقدار کد وارد شده توسط کاربر با مقدار موجود در session اِ turing_string مقایسه می شود و نتیجه بصورت 1 و 1 بازگردانده می شود. (False و True)
در اینجا برای خالی نبودن عریضه و ناقص نبودن پست، کد فایل captcha_code.php رو هم قرار می دهم، ولی توضیح آن را به پست بعد موکول می کنم.
کد PHP:
include_once('captchac_config.php');
include_once('captchac_lib.php');session_start();$turing = RandomCode($CMinSize,$CMaxSize);$_SESSION['turing_string'] = $turing;
switch ($captcha_type) {
case 1:
if ($CFontUsed == 1 ) {
$fontno = mt_rand(1,34);
$font = $fonts_dir . '/font' . $fontno . '.ttf';
}
else $font = $CFontURL;$length = strlen($turing);$data = array();$image_width = $image_height = 0;
for($i=0; $i<$length; $i++) {
$char = substr($turing, $i, 1);
$size = mt_rand($CFontSizeMin, $CFontSizeMax);
$angle = mt_rand($CFontRotMin, $CFontRotMax);
$bbox = ImageTTFBBox( $size, $angle, $font, $char );
$char_width = max($bbox[2], $bbox[4]) - min($bbox[0], $bbox[6]);
$char_height = max($bbox[1], $bbox[3]) - min($bbox[7], $bbox[5]);
$image_width += $char_width + $CFontPadding;
$image_height = max($image_height, $char_height);
$data[] = array(
'char' => $char,
'size' => $size,
'angle' => $angle,
'height' => $char_height,
'width' => $char_width,
);
}$x_padding = 12;
if ( $CSize == 1 )
{
$image_width += ($x_padding * 2);
$image_height = ($image_height * 1.5) + 2;
}
else {
$image_width = $CSizeWidth;
$image_height = $CSizeHeight;
}$im = ImageCreate($image_width, $image_height);$cs = mt_rand(1,3);$d1 = $d2 = $d3 = 0;
while ( ($d1<50) AND ($d2<50) AND (d3<50) )
{
$r = mt_rand(200,255);
$g = mt_rand(200,255);
$b = mt_rand(200,255);
$d1 = abs($r-$g);
$d2 = abs($r-$b);
$d3 = abs($g-$b);
}$color_bg = ImageColorAllocate($im, $r, $g, $b );$color_border = ImageColorAllocate($im, round($r/2), round($g/2), round($b/2));$color_line0 = ImageColorAllocate($im, round($r*0.85), round($g*0.85), round($b*0.85) );$color_elipse0 = ImageColorAllocate($im, round($r*0.95), round($g*0.95), round($b*0.95) );$color_elipse1 = ImageColorAllocate($im, round($r*0.90), round($g*0.90), round($b*0.90) );
$d1 = mt_rand(0,50);
$d2 = mt_rand(0,50);
$d3 = mt_rand(0,50);$color_line1 = ImageColorAllocate($im, $r-$d1, $g-$d2, $b-$d3 );$d1 = $d2 = $d3 = 0;
while ( ($d1<100) AND ($d2<100) AND (d3<100) )
{
$r = mt_rand(0,150);
$g = mt_rand(0,150);
$b = mt_rand(0,150);
$d1 = abs($r-$g);
$d2 = abs($r-$b);
$d3 = abs($g-$b);
}
switch ( $CFontColorType )
{
case 1 : $color_text = ImageColorAllocate($im, $r, $g, $b );
break;
case 2 : $color_text = ImageColorAllocate($im, 0, 0, 0 );
break;
case 3 : $color_text = ImageColorAllocate($im, 255, 255, 255 );
break;
case 4 : $color_text = ImageColorAllocate($im, $color_text_r, $color_text_g, $color_text_b );
break;
}$noiset = mt_rand(1,2);
if ( $CBackgroundType == 1 )
{
switch ($noiset) {
case '1' :
for($l=0; $l<10; $l++) {
$c = 'color_elipse' . ($l%2);
$cx = mt_rand(0, $image_width);
$cy = mt_rand(0, $image_width);
$rx = mt_rand(10, $image_width);
$ry = mt_rand(10, $image_width);
ImageFilledEllipse($im, $cx, $cy, $rx, $ry, $$c );
}; break;
case '2' :
for($l=0; $l<10; $l++) {
$c = 'color_line' . ($l%2);
$lx = mt_rand(0, $image_width+$image_height);
$lw = mt_rand(0,3);
if ($lx > $image_width) {
$lx -= $image_width;
ImageFilledRectangle($im, 0, $lx, $image_width-1, $lx+$lw, $$c );
} else ImageFilledRectangle($im, $lx, 0, $lx+$lw, $image_height-1, $$c );
}; break;
}
}
if ( $CBackgroundType == 0 )
{
$image_data=getimagesize($CBackgroundFile);
$image_type=$image_data[2];
if($image_type==1) $img_src=imagecreatefromgif($CBackgroundFile);
elseif($image_type==2) $img_src=imagecreatefromjpeg($CBackgroundFile);
elseif($image_type==3) $img_src=imagecreatefrompng($CBackgroundFile);
if ( $CBackgroundFillType == 1 ) {
imagesettile($im,$img_src);
imagefill($im,0,0,IMG_COLOR_TILED);
}
else imagecopyresampled($im,$img_src,0,0,0,0,$image_width,$image_height,$image_data[0],$image_data[1]);
}$pos_x = $x_padding + ($CFontPadding / 2);
foreach($data as $d) {
$pos_y = ( ( $image_height + $d['height'] ) / 2 );
ImageTTFText($im, $d['size'], $d['angle'], $pos_x, $pos_y, $color_text, $font, $d['char'] );
$pos_x += $d['width'] + $CFontPadding;
}ImageRectangle($im, 0, 0, $image_width-1, $image_height-1, $color_border);
switch ($output_type) {
case 'jpeg':
Header('Content-type: image/jpeg');
ImageJPEG($im,NULL,100);
break;
case 'png':
default:
Header('Content-type: image/png');
ImagePNG($im);
break;
}ImageDestroy($im);
break;
case 2:
break;
}session_write_close();?>
موفق باشید

ا
+ نوشته شده در شنبه ۱۰ مهر ۱۳۸۹ ساعت 15:19 توسط مصطفی اقدام طلب
|