Søger du en specifik kategori?

 



Oprettet tir. d. 03. februar 2009 kl. 00:35

hkb-x
hkb-x (10.942 point)
Guidens karaktér
1
2
3
4
5

CAPTCHA: et script til at kende forskel på computere og mennesker!

En CAPTCHA er en metode til at kende forskel på mennesker og computere via teksgenkendelse på et billede. Dette bruges ofte for at ungå spam af ens side via forms og andre input. Kan selvfølgeligt bruges i alle tænkelige og utænkelige scenarier hvor man v
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) er en metode til at kende forskel på mennesker og computere via teksgenkendelse på et billede. Det bruges oftest i sign-up form på hjemmesider for at undgå spam (ikke spam som i spam mails men f.eks. kan man undgå at en computer begynder at fylde hele ens gæstebog med reklamer osv).


Hele princippet med dette CAPTCHA system er at der dannes en tekststreng på 4 tegn angivet i $tegn og den gemmes så i sessionen $_SESSION['tekst'] til senere validering.

Helt basalt dannes der et billede på 200x60 pixels der så lægges følgende lag oven på:

1. Først laves der en baggrund af tilføldige lyse pixels.
2. På den kaster vi så vores tekst som vi tilfældigt udvælger fra $tegn og gemmer i $_SESSION['tekst'].
3. Der efter kaster vi en blanding af linier og cirkler overn på teksten.
4. Til sidst kaster vi så et begrænset antal pixels overn på både tekst og linier.

Nå teksten genereres bliver den både placeret tilfældigt i forhold til hinanden (dog baseret på den forriges position) samt de får en tilfældig vinkel, skriftstørrelse og skrifttype.

De forskellige skrifttyper angives i arrayet $skrifttyper[] og kan ændres efter for godt befindende.

Meningen er så at brugeren aflæser billedet og indtaster de 4 tegn i et input-felt der sennes sammen med det andet data. Serveren kan der efter validere brugerens input ved at sammenligne det med SESSION['tekst'].


Jeg vil gennemgå de enkelte dele bid for bid men først tager vi hele scriptet her:

(Det kan også findes i en pænere .phps version her: <a href="http://www.hkb.it/ (...))

<?

session_start();

header("Content-type: image/png");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

$skrifttyper[] = "Arial.ttf";
$skrifttyper[] = "Tahoma.ttf";
$skrifttyper[] = "Impact.ttf";
$skrifttyper[] = "Verdana.ttf";
$skrifttyper[] = "Georgia.ttf";



// Basis billedet

$billede = imagecreatetruecolor(200, 60);



// En god barggrundsstøj men kun med lyse farver

for($i=0;$i<(200*60);$i++) {

    $color = imagecolorallocate($billede, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));

    imagesetpixel($billede, ($x - 1), $y, $color);


    $x += 1;

    if($x > 200) {

        $y += 1;
        $x = 1;

    }
}



// Så selve teksten

$tegn = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz";

for($i=0;$i<4;$i++) {

    $input .= substr($tegn, mt_rand(0, (strlen($tegn) - 1)), 1);

}

$_SESSION['tekst'] = $input;


$x = mt_rand(10, 60);
$y = mt_rand(35, 50);

for($i=0;$i<strlen($input);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 155), mt_rand(0, 155), mt_rand(0, 155));

    $font = "C:/Windows/Fonts/".$skrifttyper[mt_rand(0, (count($skrifttyper) - 1))];


    imagettftext($billede, mt_rand(25, 30), mt_rand(-10, 10), $x, $y, $color, $font, substr($input, $i, 1));

    $x += mt_rand(25, 40);
    $y += mt_rand(-5, 5);

}



// Derefter nogle streger og cirkler

for($i=0;$i<mt_rand(4, 6);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200));


    if(mt_rand(0, 2) == 1) {

        imageellipse($billede, mt_rand(50, 150), mt_rand(10, 50), mt_rand(10, 60), mt_rand(10, 60), $color);

    } else {

        imageline($billede, mt_rand(0, 50), mt_rand(0, 60), mt_rand(100, 200), mt_rand(0, 60), $color);

    }

}



// Og igen nogle tilfældige pixels overnpå for at gøre forvirringen total

for($i=0;$i<mt_rand(250, 500);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));

    imagesetpixel($billede, mt_rand(0, 200), mt_rand(0, 60), $color);

}



imagepng($billede);

?>


Det var lidt af en mundfuld men lad os tage det lidt af gangen.

Det basale
Først kører vi session_start() så vi er klar når vi skal gemme vores teksstreng i en session. Der erfter angiver vi et par headers der fortætter at det er et png billede og at det ikke skal gemmes i browserens cache (er så op til den enkelte browser om den vil godtage det). Vi definerer også lide de skrifttyper vi vil bruge i arrayet $skrifttyper.

Her efter danner vi et 'true color' billede på 200x60 px til at lave vores CAPTCHA på.

session_start();

header("Content-type: image/png");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

$skrifttyper[] = "Arial.ttf";
$skrifttyper[] = "Tahoma.ttf";
$skrifttyper[] = "Impact.ttf";
$skrifttyper[] = "Verdana.ttf";
$skrifttyper[] = "Georgia.ttf";



// Basis billedet

$billede = imagecreatetruecolor(200, 60);



Baggrundsstøj
En af de bedste måder at skjule teksten på er at lave masser af baggrundsstøj da det er meget nemmere for an computer at læse tekst på en ensfarvet baggrund. Dette gøres ved at vi kører samtlige pixels på billedet igenem og giver dem en tilfældig farve med imagesetpixel(). Jeg har dog valgt kun at bruge farver fra den lysere del af skalaen så de ikke blander sig for meget med teksten.

for($i=0;$i<(200*60);$i++) {

    $color = imagecolorallocate($billede, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));

    imagesetpixel($billede, ($x - 1), $y, $color);


    $x += 1;

    if($x > 200) {

        $y += 1;
        $x = 1;

    }
}



Selve teksten
Selve teksten genereres ved at vælge 4 tilfældige tegn ud fra den teksstreng der angiver hvilke tegn vi vil bruge. Bag efter vælger vi så et startpunkt for teksten med kordinaterne $x, $y.

$tegn = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

for($i=0;$i<4;$i++) {

    $input .= substr($tegn, mt_rand(0, (strlen($tegn) - 1)), 1);

}


$x = mt_rand(10, 60);
$y = mt_rand(35, 50);


Her efter kaster vi den ind på billedet med en tilfældig frave (dog kun mørke farver der ikke blander sig med baggrundsstøjen), en tilfældig skrifttype, en tilfældig vinkel, en tilfældig skriftstørrelse og på position $x, $y.

Bag efter angiver vi en ny position for $x, $y (der vil være placeringen af det næste tegn). $x går fra 25 - 50 da bogstaverne jo ikke bare kan spredes tilfældigt men skal stå i rækkefølge hvor imod $y går fra -5 - 5 da bogstaverne både kan placeres lidt nede og oppe i forhold til hinanden.

Til sidst gemes det enkelte bogstav i $_SESSION['tekst'] til senere validering.

for($i=0;$i<strlen($input);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 155), mt_rand(0, 155), mt_rand(0, 155));

    $font = "C:/Windows/Fonts/".$skrifttyper[mt_rand(0, (count($skrifttyper) - 1))];


    imagettftext($billede, mt_rand(25, 30), mt_rand(-10, 10), $x, $y, $color, $font, substr($input, $i, 1));

    $x += mt_rand(25, 40);
    $y += mt_rand(-5, 5);


    $_SESSION['tekst'] .= substr($input, $i, 1);
}



Streger og Cirkler
Her efter genereres der nogle streger og cirkler oven på vores tekst. Der vælges tilfældigt om der skal laves en streg eller en cirkel, der er dog dobbelt så stor sansynlighed for at tegne en streg.

for($i=0;$i<mt_rand(4, 6);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200));


    if(mt_rand(0, 2) == 1) {

        imageellipse($billede, mt_rand(50, 150), mt_rand(10, 50), mt_rand(10, 60), mt_rand(10, 60), $color);

    } else {

        imageline($billede, mt_rand(0, 50), mt_rand(0, 60), mt_rand(100, 200), mt_rand(0, 60), $color);

    }

}



Tilfældige Pixels
Til sidst kaster vi en masse blandede pixels ud over det hele for at skjule bogstaverne yderligere. Dette gøres på samme måde som i starten bare 100% tilfældigt og med brug af hele fravespekteret.

for($i=0;$i<mt_rand(250, 500);$i++) {

    $color = imagecolorallocate($billede, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));

    imagesetpixel($billede, mt_rand(0, 200), mt_rand(0, 60), $color);

}


Som det sidste kaster vi så det genererede billede afsetd til brugeren.

imagepng($billede);



I praksis brug

Et eksempel på brug af billedet i praksis kan ses her: <a href="http://www.hkb.it/ (...)

Billedet der sendes burde nu kun kunne læses af mennesker. Jeg har testet det op imod "What the font" (<a href="http://www.myfonts.com/ (...)) og den har aldrig været i stand til bare at komme tæt på bare et af bogstaverne.

En god ide når man bruger det i praksis er at give brugeren mulighed for at kunne reloade billedet hvis det er for utydeligt. Det kan gøres med denne lille smule JavaScript.

<img src="http://www.hkb.it/ (...) id="CAPTCHA" /><br />
Er billedet for utydeligt? så < a href="#" onclick="document.getElementById('CAPTCHA').src='http://www.hkb.it/ (...) + Math.random();">klik her</ a>.


Det er også grunden til at jeg genererer $_SESSION['tekst'] i selve billedet.

Yderligere kommentarer
Da jeg bruger så mange tilfældige værdier har jeg bevist valgt at bruge mt_rand() istedet for bare at bruge rand(). Det giver faktisk en målbar forskel på genereringen af billedet.

Hvis din hjemmeside hostes på en server du ikke selv kan administrere har du højest sansynligt ikke adgang til C:/Windows/Fonts/ så du må eventuelt prøve en anden sti. Jeg har endnu ikke testet om imagettftext() vil fungere hvis skrifttypen ikke er instaleret på serveren men bare ligger i en tilfældig mappe.

Svar
obhat: Umiddelbart vil jeg ikke tro det da selve billefunktionerne bruger GDlib som er "indbygget" i PHP men om ASP har en lignende tilføjelse ved jeg ikke.

windcape: Jahr i know... er derfor jeg også har lavet den i .phps format: <a href="http://www.hkb.it/ (...)

Skrevet ons. d. 30. maj 2007 kl. 13:49| #1

obhat (9.910 point)
Kunne det laves i ASP?

Skrevet ons. d. 30. maj 2007 kl. 19:17| #2

rimelig godt, dog er php koden lidt rodet, mangler indents og burde scopes af pratiske årsager. ||| obhat: Ja, hvis du installere et module der kan generere billeder. Konceptet bagved (at generere random bogstaver, og gemme i en session) er det samme for alle sprog.

Skrevet man. d. 04. juni 2007 kl. 14:44| #3

olebole (214.028 point)
Fin artikel - omend den ikke omhandler PHP's mest anvendte miljø: Linux (og andre *nix-kloner). At der mangler indrykninger, er ganske forståeligt med det elendige og outdatede interface, Eksperten stiller til rådighed for artikelskrivning. Det skal forfatteren ikke skældes ud for  =)

Skrevet tor. d. 07. juni 2007 kl. 09:25| #4

langthjem (23.626 point)
www.cimplesite.dk
God artikel. Har tit undret mig over hvordan det skulle gribes an. Det forklarer du jo godt. Jeg tror faktisk at den vil være let at overføre til ASP. Hvis man bruger ASPImage eller ASPJpeg til genereringen. Både ASPJpeg og ASPImage kan læse fonte fra en hvilken som helst mappe.

Skrevet tir. d. 19. juni 2007 kl. 09:21| #5

jensgram (38.604 point)
www.jensgram.dk
Nydeligt. Læste den ikke så intenst, men det ser fornuftigt og gennemarbejdet ud.

Skrevet søn. d. 24. juni 2007 kl. 20:28| #6

michaelthomassen (15.610 point)
Fonte kan "trækkes ud" af din egen windows installation og lægges op på serveren, hvis du ikke har adgang til fonte direkte derfra. Jeg havde ikke adgang til fonts på min webside (one.com), men ved at uploade dem og rette stien til, virkede det fint.

Skrevet ons. d. 27. juni 2007 kl. 09:39| #7


Skrevet ons. d. 10. oktober 2007 kl. 08:05| #8

dandyman (16.715 point)
Har selv lavet captcha's før men denne ser bare endnu bedre ud

Skrevet søn. d. 02. december 2007 kl. 16:58| #9


Skrevet lør. d. 02. august 2008 kl. 05:17| #10

roenving (327.724 point)
Det'r zq i orden (og GDlib kan da også bruges i asp !-)

Skrevet tor. d. 18. september 2008 kl. 20:37| #11

w13 (109.551 point)
www.2biaz.dk
Meget nyttigt!

Skrevet søn. d. 25. januar 2009 kl. 22:40| #12

supreme-creme (10.440 point)
Hvad retter i adressen til fontsne til?
Jeg har smidt dem i en mappe kaldet fonts, men får stadig fejlen med at den ikke kan loade fontsne. Hvad gør i?

Skrevet tor. d. 14. juli 2011 kl. 19:21| #13

grafik-anders (7.751 point)
Sorry, - den er væk nu ;)

Skriv en kommentar



Mest populære guides

Guidens karakter
!!!Karaktér: 3
12 stemmer
31/01 - 2011
Af: heinzdmx

Dropbox - gratis online lagerplads

Jeg vil i denne guide forklare lidt om hvad Dropbox er og også hvordan du får mest mulig plads på Dropbox. Dropbox er kort sagt en service hvor du har dine data lagt til backup på både nettet og din egen computer.
Guidens karakter
!!!Karaktér: 4
33 stemmer
02/02 - 2009
Af: jkrons

Dato- og tidsberegninger i Excel

En introduktion til simple beregninger med dato og tid i Excel. Opdateret med afsnit om beregning af tillæg.
Excel  |  Læs »
Guidens karakter
!!!Karaktér: 4
21 stemmer
06/11 - 2011
Af: fromsej

Sådan fjerner du virus og malware

Udviklingen går stærkt på "skidt"fronten, så vi har sammensat en ny og effektiv programpakke til fjernelse af det.
Virus  |  Læs »

Log ind

   

   

Seneste guides

Installer win 7
Den gode bruger


   




Tips & Tricks fra PC World

Teaser billede

Her er fem sjove danske websider du skal kende

Trænger dine lattermuskler til en omgang fitness på dansk? Vi viser vej til fem websider fyldt med humor og vanvittig satire.


Anmeldelser fra PC World

Teaser billede

Test: Denne super-tablet er iPads hårdeste konkurrent

Eee Pad Transformer Prime er frygtindgydende med sin quadcore processor og evne til at trylle sig om til bærbar. Apple bør kigge i bagspejlet, for Asus' tablet-pc kommer buldrende - og gør det...


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Nu kan du snart hente Windows 8

Den nye offentlige betaversion af Windows 8 er klar i denne måned.


Nyheder fra Computerworld

Teaser billede

Måske snart slut med Androids helt store problem

Android-platformen har længe været plaget af et særligt problem. Men måske er problemet nu ved at være elimineret.


Kurser
Samarbejdspartnere

Udgiver · © 2012 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301 · Brug af personoplysninger