Captcha: În vremurile noastre programarea este foarte accesibilă, atât de accesibilă încât după 7 zile (fără să fii avut contact cu limbaje de programare niciodată) în PHP ți-ai construit propriul bot ce poate stresa administratorii în cel mai cumplit mod.
Văd tot mai des formulare de contact neprotejate prin nimic, fără cod captcha, sau si mai rău îți bagă o adunare vizibilă din sursă. Păi serios vorbind acum, el ca programator web, nu știe că un bot lucrează cu sursa? Neatenția programatorilor web la securitate este jignitoare, scuza lor întotdeauna este că „Nimeni o să facă un bot special pentru site-ul meu”. Ei pe naiba, să-mi dea un mail că îl fac eu, dar daunele suportate de ei.
În acest tutorial vom învăța despre captcha-uri, nu articole de 3 rânduri unde prezint ce este un captcha și afișez 3 linii de cod după plec să ma culc, un tutorial amănunțit unde vom experimenta mai multe metode de captcha nu ca la alții care se cred programatori cu 3 frimituri :).
Ce este un captcha în web site?
Cu cât un captcha este mai complicat, mai întors, mai împodobit, cu atât mai imposibilă este spargerea lui. Chiar și un captcha simplu, un text drept cu un font default pe o imagine albă este foarte greu de spart, algoritmii pentru OCR fiind foarte complicați.
Cum folosim captcha în web site-urile PHP?
- Un fișier PHP generează un cod captcha, îl salvează într-o sesiune, iar apoi îl afișează ca imagine
- Vizitatorului îi este afișat codul captcha și un input unde să introducă ce caractere vede în imagine
- Datele sunt trimise prin POST sau GET la altă pagină (când vizitatorul apasă pe submit să introducă comentariul de exemplu)
- Acea pagina verifică ce a trimis el prin POST sau GET cu ce este în sesiune
- În caz că, codul nu a fost introdus corect îl anunță că a greșit și închide scriptul (exit)
Partea cea mai complicată, crearea imaginii, va fi subiectul principal al acestui articol. Dar și celelalte vor fi explicate.
Pentru a înțelege acest articol ai nevoie deja să ințelegi generarea de imagini cu PHP în web site
Introducere în web site | Captcha Simplu
În prima parte vom crea un captcha foarte simplu.
Structura fișierelor
Structura fișierelor este următoarea:
- fonts
- captcha.php
- contact.html
- submit-contact.php
Nu uitați să downloadați fontul, click pe el să-l descărcați.
Crearea imaginii în web site
Cod captcha.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?php session_start(); $image_width = 200; $image_height = 60; $ih = imagecreate( $image_width , $image_height ); $negru = imagecolorallocate( $ih , 0, 0, 0); // background $rosu = imagecolorallocate( $ih , 255, 0, 0); // text imagefill( $ih , 0, 0, $negru ); // umplem backgroundul cu negru $cod_captcha = substr ( str_shuffle ( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, 5); $_SESSION [ 'cod' ] = $cod_captcha ; // salvam codul in sesiune putenv( 'GDFONTPATH=' . realpath ( 'fonts/' )); // setam folderul pentru fonturi $font = 'KiteOne' ; # Cu coords centram text-ul. $coords = imagettfbbox(29, 0, $font , $cod_captcha ); // Coordonate pentru a centra textul $start_x = ( $image_width - $coords [2])/2; imagettftext( $ih , 29, 0, $start_x , 40, $rosu , $font , $cod_captcha ); header( 'Content-type: image/png' ); imagepng( $ih ); ?> |
Pagina unde afișăm captcha în web site
Eu aici îți voi da ca exemplu o pagină de contact, unde când dai click pe imagine îți schimbă codul captcha primit (pentru asta vom folosii JavaScript).
Cod contact.html:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<!doctype html> <html lang= "en" > <head> <meta charset= "UTF-8" > <title>Contacteaza-ma</title> </head> <body> <form action= "submit-contact.php" method= "POST" > <table cellpadding= "5" border= "3" style= "width:50%; margin:0 auto;" > <tr> <td>Subiect</td> <td><input type= "text" name= "subiect" ></td> </tr> <tr> <td>Mesaj</td> <td> <textarea name= "mesaj" style= "width:90%;" rows= "3" ></textarea> </td> </tr> <tr> <td>Captcha</td> <td> <img src= "captcha.php" id= "captcha" onclick= "this.src='captcha.php?'+new Date().getTime()" alt= "" > <br><sub>* Scrieti textul din imagine in casuta de mai jos</sub><br> <input type= "text" name= "captcha" > </td> </tr> </table> <input type= "submit" value= "Trimite mesaj" style= "margin-right:25%; float:right;" /> </form> </body> </html> |
Folosim la javascript în adresa url și time-ul curent ca un bypass pentru „cache-ul” care se face la imagini.
Validarea captcha-ului în web site
În această etapă am primit codul captcha din formular și trebuie să vedem dacă este corect.
Cod submit-contact.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?php session_start(); if ( $_SERVER [ 'REQUEST_METHOD' ] != 'POST' ){ // Metoda de REQUEST nu este POST header( 'Location: contact.html' ); exit ; } if (isset( $_SESSION [ 'captcha' ])){ if ( $_POST [ 'captcha' ] == $_SESSION [ 'captcha' ]){ // Aici am trimite emailul dar este doar un exemplu echo 'Mail trimis cu success!' ; } else { echo 'Codul captcha este gresit! Veti fi redirectionat inapoi in 3 secunde.' ; header( 'Refresh: 3; url=contact.html' ); exit ; } unset( $_SESSION [ 'captcha' ]); // stergem captcha-ul } else { echo 'Captcha-ul nu a fost primit! Veti fi redirectionat inapoi in 3 secunde.' ; header( 'Refresh: 3; url=contact.html' ); exit ; } ?> |
În această parte lucrăm doar cu fișierul captcha.php, structura rămâne aceeași cu cu cea de la Introducere în web site | Captcha Simplu, dar poate suferii mici modificari pe parcurs.
Font aleatoriu îm web site
O bună practică este folosirea fonturilor extravagante, cât mai ciudate, dar o și mai bună practică este folosirea unui font aleatoriu (adică dintr-o lista de fonturi alegeți unul la întâmplare cu php la fiecare vizită), să complicăm munca bot-ului. Însă nu este bine să exagerați, să folosiți maxim 10 fonturi. În primul va fi necesar să descărcați fonturile și să puneți toate fonturile în folder-ul fonts.
Structura fișiere nouă în webs site
- fonts
- KiteOne.ttf
- Playball.ttf
- JustMeAgainDownHere.ttf
- Englebert.ttf
- Yesteryear.ttf
- Spirax.ttf
- Nosifer.ttf
- JollyLodger.ttf
- Davonshire.ttf
- Finger Paint.ttf
- captcha.php
- contact.html
- submit-contact.php
Cod captcha.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<?php session_start(); $image_width = 200; $image_height = 60; $ih = imagecreate( $image_width , $image_height ); $negru = imagecolorallocate( $ih , 0, 0, 0); // background $rosu = imagecolorallocate( $ih , 255, 0, 0); // text imagefill( $ih , 0, 0, $negru ); $cod_captcha = substr ( str_shuffle ( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, 5); $_SESSION [ 'captcha' ] = $cod_captcha ; // salvam codul in sesiune putenv( 'GDFONTPATH=' . realpath ( 'fonts/' )); // setam folderul pentru fonturi $fonturi = array ( 'Playball' , 'JustMeAgainDownHere' , 'Englebert' , 'Yesteryear' , 'KiteOne' , 'Spirax' , 'Nosifer' , 'JollyLodger' , 'Davonshire' , 'Finger Paint' ); $font = $fonturi [ rand(0, count ( $fonturi )-1) ]; // alegem un font random $coords = imagettfbbox(29, 0, $font , $cod_captcha ); // Coordonate pentru a centra textul $start_x = ( $image_width - $coords [2])/2; imagettftext( $ih , 29, 0, $start_x , 40, $rosu , $font , $cod_captcha ); header( 'Content-type: image/png' ); imagepng( $ih ); ?> |
Deoarece fonturile sunt foarte periculoase când vine vorba de majuscule sau minuscule trebuie să lăsăm vizitatorul să le bage cum dorește, deci schimbăm puțin validarea.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php session_start(); if ( $_SERVER [ 'REQUEST_METHOD' ] != 'POST' ){ // Metoda de REQUEST nu este POST header( 'Location: contact.html' ); exit ; } if (isset( $_SESSION [ 'captcha' ])){ if ( strtolower ( $_POST [ 'captcha' ]) == strtolower ( $_SESSION [ 'captcha' ])){ // Aici am trimite emailul dar este doar un exemplu echo 'Mail trimis cu success!' ; } else { echo 'Codul captcha este gresit! Veti fi redirectionat inapoi in 3 secunde.' ; header( 'Refresh: 3; url=contact.html' ); exit ; } unset( $_SESSION [ 'captcha' ]); // stergem captcha-ul } else { echo 'Captcha-ul nu a fost primit! Veti fi redirectionat inapoi in 3 secunde.' ; header( 'Refresh: 3; url=contact.html' ); exit ; } ?> |
Linii
Încă o bună strategie mai este să adăugați linii în captcha. Gândiți-vă logic, linii cu aceeași culoare ca textul, în număr de ~20, vor încurca complet un algoritm slab făcut.
Cod captcha.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?php session_start(); $image_width = 200; $image_height = 60; $ih = imagecreate( $image_width , $image_height ); $negru = imagecolorallocate( $ih , 0, 0, 0); // background $rosu = imagecolorallocate( $ih , 255, 0, 0); // text imagefill( $ih , 0, 0, $negru ); $cod_captcha = substr ( str_shuffle ( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, 5); $_SESSION [ 'captcha' ] = $cod_captcha ; // salvam codul in sesiune putenv( 'GDFONTPATH=' . realpath ( 'fonts/' )); // setam folderul pentru fonturi $font = 'KiteOne' ; $coords = imagettfbbox(29, 0, $font , $cod_captcha ); // Coordonate pentru a centra textul $start_x = ( $image_width - $coords [2])/2; imagettftext( $ih , 29, 0, $start_x , 40, $rosu , $font , $cod_captcha ); # Urmeaza sa cream un numar intre 5 si 15 de linii cu acceasi culoare ca textul $linii = rand(5,15); for ( $i =1; $i < $linii ; $i ++) { imageline( $ih , rand(1, $image_width ) , rand(1, $image_height ), rand(1, $image_width ) , rand(1, $image_height ), $rosu ); } header( 'Content-type: image/png' ); imagepng( $ih ); ?> |
Puncte
Această practică nu am mai vazut-o prin alte părți, dar:
- 1. Îmi place cum arată
- 2. Nu încurcă
- 3. Nu poate face nimic rău, decât bine
Cod captcha.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<?php session_start(); $image_width = 200; $image_height = 60; $ih = imagecreate( $image_width , $image_height ); $negru = imagecolorallocate( $ih , 0, 0, 0); // background $rosu = imagecolorallocate( $ih , 255, 0, 0); // text imagefill( $ih , 0, 0, $negru ); $cod_captcha = substr ( str_shuffle ( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, 5); $_SESSION [ 'captcha' ] = $cod_captcha ; // salvam codul in sesiune putenv( 'GDFONTPATH=' . realpath ( 'fonts/' )); // setam folderul pentru fonturi $font = 'KiteOne' ; $coords = imagettfbbox(29, 0, $font , $cod_captcha ); // Coordonate pentru a centra textul $start_x = ( $image_width - $coords [2])/2; imagettftext( $ih , 29, 0, $start_x , 40, $rosu , $font , $cod_captcha ); $linii = rand(5,15); for ( $i =1; $i < $linii ; $i ++) { imageline( $ih , rand(1, $image_width ) , rand(1, $image_height ), rand(1, $image_width ) , rand(1, $image_height ), $rosu ); } # Adaugam 200 de puncte for ( $j =0; $j < 200; $j ++) { $x = rand(1, $image_width ); $y = rand(1, $image_height ); # Folosesc imageline pentru a desena un punct deoarece are aceleasi coordonate de pornire ca de oprire imageline( $ih , $x , $y , $x , $y , $rosu ); } header( 'Content-type: image/png' ); imagepng( $ih ); ?> |
Dacă ți-a plăcut acest tutorial și ți-a fost util lasă comentariul tău!
Blogger din anul 2004, fecioară, iubitor de grafică, Senior WebMaster la StoreDay.ro, Senior Graphic Designer, Senior Web Designer, Senior Web Commerce. Sunt un tip plin de viață și inovator în creativitate.
Nice technical information.
Thank me