GD v praxi - Overovací kód v obrázku

GD v praxi - Overovací kód v obrázku

Po seriály "Práca s GD knižnicou" prichádza nový článok a to PHP v praxi. Cieľom bude dosiahnúť odoslanie dát prostredníctvom formuláru, ktoré bude fungovať iba v prípade, ak opíšete s obrázku náhodne vygenerovaný text.
01.png
Jelikož jsme si toho o GD řekli už dost měli bychom přejít k příkladům v praxi. Jistě znáte např. při přihlašování, psaní komentáře, že je tam obrázek, z kterého musíte opsat text aby jste mohli dále pokračovat. Tak přesně toto si dnes uděláme. Budeme k tomu potřebovat obrázek pojmenovaný pozadi2.png, pravděpodobně i font arial.ttf (naleznete ve složce s windows/fonts) a trochu času.
Pozadi2.png
02.png

Budeme používat pár funkcí, o kterých jsme si ještě neřekli. A to rand a char.
Rand (od, do)
Funkce generuje náhodné číslo v zadaném rozmezí.
Char (cislo)
Funkce převede číslo na znak podle ascii tabulky. V ascii tabulce je každý znak reprezentován nějakým číslem. ASCII tabulkou se dále nebudu zabývat (to není náplní tohoto článku). Tuto funkci použijeme proto, že funkce rand dokáže generovat pouze náhodné číslo. A mi potřebujeme i písmena A-Z, a-z. Zde vidíte tabulku bez netisknutelných znaků (proto začíná až číslem 32)

A jdeme na to…...
<?php

session_start();

$obrazek = imagecreatefrompng("pozadi2.png");
Jelikož nějak musíme ověřit, zdali bylo zadáno správné heslo použijeme pro to session. Vytvoříme obrázek z našeho pozadi2.png.
for ($i=0;$i<5;$i++)

{

while(strlen($str)!=1){

$random=rand(48,123);

if( ($random>47 && $random<58) || ($random>96 && $random<123) ||

($random>64 && $random<91) ){

$str.=chr($random);

}

} 

$text .= $str;

$textcolor = imagecolorallocate($obrazek,rand(0,130),rand(0,130),rand(0,130));



imagettftext ($obrazek,rand(15,25),rand(-45,45),15+($i*38),35, $textcolor,"arial.ttf",$str) ;



$str = NULL;

}
Následuje cyklus for, který nám zajistí vygenerování 5 znaků do obrázku. Cyklus While se bude provádět tak dlouho dokud se do $radon nevygeneruje číslo které podle ascii přestavuje námi požadované znaky. Když se vygeneruje správné číslo provede se $str.=chr($random); což nám do $str přiřadí znak z vygenerovaného čísla podle ascii. Když už se to provede přidá se písmeno do proměnné $text (abychom i na konci cyklu for věděli jaký text jsme vygenerovali. Poté se provede imagecolorallocate kde se pomocí funkce rand vygenerují hodnoty pro barvu (abychom v obrázku měli různé barvy). No a nakonec se to vypíše velikostí 15-25, pod úhlem -45° až 45° fontem arial. $str se vynuluje a to celé se opakuje 5*.
$_SESSION['string']=$text;

header("Content-type: image/png");

imagepng($obrazek);

imagedestroy ($obrazek)

?>>
Nyní se do session uloží $text ve které je zapsán celý vygenerovaný text. Odešle se hlavička, obrázek a uvolní se systémové prostředky. Tak a máme celý kód na generování obrázku.

Jedinou chybu na kráse to má že díky odesílání session nemůžeme před kód dát nic jiného. Takže kód je ještě potřeba trochu upravit, aby se session mohlo odeslat i když je kód třeba v formuláři. To už nechám na vás…. Následující kód představuje jak by jste to mohli udělat.
<?php

session_start();

if (!isset($_GET['generuj'])) {

for ($i=0;$i<5;$i++)

{

while(strlen($str[$i])!=1){

$random=rand(48,123);

if( ($random>47 && $random<58) || ($random>96 && $random<123) ||

($random>64 && $random<91) ){

$str[$i] = chr($random);

}

}



$text .= $str[$i];



}

$_SESSION['string']= $text;

$GLOBALS['text'] = $text;

}





elseif (isset($_GET['generuj'])){

$GLOBALS['text'] = $_SESSION['string'];

$obrazek = imagecreatefrompng("pozadi2.png");

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



$textcolor = imagecolorallocate($obrazek,rand(0,130),rand(0,130),rand(0,130));

$pismenko = substr($GLOBALS['text'],0+$i,1);





imagettftext ($obrazek,rand(15,25),rand(-45,45),15+($i*38),35, $textcolor,"arial.ttf",$pismenko) ;

}

header("Content-type: image/png");

imagepng($obrazek);

imagedestroy ($obrazek);

exit();

};

?>



<?php echo '<?xml version="1.0" encoding="ISO-8859-2"?>'; ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cz">





<head>

<!-- meta tags and language -->

<meta http-equiv="content-language" content="cz" />

<meta name="language" content="cz" />

<meta name="document-language" content="cz" />

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2" />



<title>Ukázkový formulář</title>



</head>



<body>



<form method="post" action="kontrola.php">

<fieldset>

<img src = "formular.php?generuj" alt="code"/><br/>

Opis kod:<input type="text" name="kod" size="24"/> <br/>

Vase zprava:<br/>

<textarea rows="7" name="text" cols="31"></textarea><br/>

<input type="submit" value="Odeslat" name="odeslat"/>

<input type="reset" value="Obnovit" name="obnovit"/>

</fieldset>

</form>

</body>

</html>
A nakonec jen soubor kontrola.php
Zde stačí dát něco ve smyslu.
<?

if( $_SESSION['string'] == $_POST['kod'] )

{

echo 'Ano kód jsi opsal správně. Gratuluji';

// váše zpracování zprávy

}

else

{

echo 'Spamery nemám rád.... Zadal jsi špatný kód';

}

?>
Výsledky(príklady):
03.png

A na úplný závěr si zde můžete stáhnout celý skript i s pokusným formulářem. Nebo se na skript podívat na: http://vyrvarimweb.wz.cz/formular.php(formulář) a http://vyrvarimweb.wz.cz/kod.php (jen generování obrázku). Celý zdrojový kód si můžete stáhnout zde.
Alternatívne verzie: Text PDF Voice
Autor: Los.Pavlos · Kategória: Programovanie · Dátum: 16.07.2005 16:42

Komentáre

#1 pjotr Web E-mail
00.00.0000 00:00
Ešte by som doplnil, že pokiaľ sa niekto pohybuješ myšou ponad obrázok, mohol by tam byť nejaký atribút title="", ktorý by opísal, čo sa má urobiť, pokiaľ obrázok nikto nevidí.

Niektorí to majú vyriešené tak, že príspevok sa môže poslať emailom, pokiaľ nevidia obrázok. A to všetko by malo byť práve v title="".

#2 Los.Pavlos E-mail
00.00.0000 00:00
hmmmm dobrá připomínka..... já tam nacopal jen alt. Takže až se tu ukáže PaBi3 tak mu napíšu jestli by to mohl upravit...No a jak tak koukam tak pod článkem ještě chybí odkaz na rar soubor s zdrojáky.....

#3 andy E-mail
15.09.2006 19:10
....nejde stiahnut ten archiv. neda sa s tym nieco robit ?

#4 ribi Web E-mail
15.09.2006 21:45
Problém nie je na strane PaBi3.com, ale na strane WebZdarma.cz. U WebZdarma človek nikdy nevie...

#5 andy E-mail
16.09.2006 08:12
a neda sa to poslat mailom ? Prosim ;)

#6 trezor
17.10.2006 11:12
Stiahnuť sa to dá, ale nedá sa to potom otvoriť.
Inak, veľmi dobrý úvodný seriál ku GD. Nebude podrobnejšie pokračovanie?

#7 admin Web E-mail
17.10.2006 13:05
admin Zatiaľ sa žiadne pokračovanie neplánuje.

#8 Pepik Web E-mail
26.10.2006 19:27
Vedel by niekto kde sa da stiahnut nejaka navstevna kniha s tymto overovacim kodom? popripade takato navstevna kniha? ale najlepsie by bolo bez pouzitia sql

#9 Peto
24.04.2007 11:18
Ale ma to jednu chybicku a to taku ze pokial niekto opisuje kod niekto iny moze zatial kliknut na tu istu stranku a vygenerovat si novy kod a ten sa nasledne odosle do session a stary kod prveho navstevnika uz nebude platany........a ciste teoreticky by si navzajom takto mohli resetovat kody a teda by sa ani na 100 pokus nikto nedostal dalej!

#10 critter
26.05.2007 00:11
[9] 2Peto > to je nesmysl co rikas - protoze kazdy, kdo vleze na stranku se zobrazenym kodem, tomu se ulozi JEHO vygenerovany kod do JEHO session. Tj. nikdo nemuze nikomu jinemu nic ovlivnovat. To by odporovalo principu fungovani session...

#11 qaws
29.05.2007 20:19
2critter -> nie je to blbost, ak to robi jeden clovek. Casto sa mi stava, ze otvorim jednu stranku v dvoch zalozkach a prvy krat zadam kod zle, ale na druhy krat to uz ide (ako napriklad teraz - bol som rozpoznany ako robot).

#12 admin Web E-mail
30.05.2007 11:25
admin [11] qaws, máš pravdu v tom: "ak to robí jeden človek". Pri načítaní druhej stránky sa vygeneruje nový kód do captcha obrázku, takže captcha kód na prvej stránke už nefunguje.

#13 peter E-mail
14.06.2007 17:11
ospravedlnujem sa, session som celkom spravne nepochopil, funguje tak ako sa tu uz spominalo... :)

#14 spl!te Web E-mail
19.08.2007 19:27
Bohužel, logické chyby:

Představ si že tuhle captchu použiju při odeslání komentáře k článku. Přijdu na index s mým oblíbeným Firefoxem, dostanu od php svoje PHPSSID, naklikám si články do tabů a budu třeba u dvou z nich chtít přidat komentář.

Jenomže - právě protože jsem si stránku rozklikal do tabů, mám u každé stejný phpssid - a s každým generováním se mi v session přepíše hodnota stringu který se porovnává při validaci...
Takže validace proběhne správně jen u naposledy generovaného obrázku (v tomhle příkladě u tabu který jsem si otevřel naposledy). Všechny ostatní taby budou sice zobrazovat v captche unikátní kód, ale při porovnání budou očekávat jen ten jeden poslední...

Špatně se to vysvětluje, proto tady píšu jak by mělo vypadat ověřování - snad to pochopíte z něj...


if( $_SESSION[$unikatni_id]['string'] == $_POST['kod'])


Z toho ovšem vyvstává problém že ono $unikatni_id musí být předáno zároveň s formulářem, ale to také není problém. Úplně totiž stačí přidat:


<input type="hidden" name="unikatni_id" value="<?=$unikatni_id>">


Na generování unikátního ID jsem si já osobně napsal takovou sladkou funkci


function getMyUID(){
return substr(md5(time()+rand(0,100)), rand(0,16), rand(17,32));
}


Navíc, představ si že odešlu spam. Obrázek musím opsat jen poprvé, pak už stačí se jakkoliv vyhnout znovuvygenerování obrázku který by mi přepsal session (případně pokud kód rozšíříš o mnou navrhované unikatni_id tak si ani s tím nemusím lámat hlavu) a můžu zvesela používat k validaci starý kód znova a znova a znova a znova.

Řešení je také prosté, stačí jednoduše po dokončení validace přidat

unset($_SESSION[$unikatni_id]['string']);

Jinak až na tuhle chybnou implementaci super tutorial, naučil mě jak se naklápí písmenka

#15 wenzell E-mail
25.08.2007 15:31
poradte nekdo prosim jak se musi upravit ten zdrojak aby to generovalo na jpg

#16 Pheneus E-mail
19.07.2008 22:09
[14] spl!te,[14] spl!te,

Ahoj prostrednictvom toho inputu s typom hidden by som to nerobil lebo v html je mozne vycitat hodnotu kodu s unikatnym kodom a to potom uz sa nemusa ani ta captcha pouzivat

#17 Tom
03.09.2012 16:39
Veľmi pekný článok.
spl!te to ešte vylepšil.
Pheneus Pokús sa to prečítať ešte raz, pozorne a snaž sa to pochopiť. do toho hidden inputu sa zapíše ID nie KÓD. a to ID oskazuje na session v ktorom je ten kód. Ak sa na to pozrieš lepšie tak spl!te vlastne len rozšíril pole a geniálne vyriešil problém s otvorením viacerých stránok naraz.

PS: Som si vedomí toho že píšem príspevok po 4-och rokoch ale musel som to napísať aby sa ľudia nebáli používať hidden input. Samozrejme že sa dá u uživateľa zmeniť/prečítať hodnota ale v tomto prípade by mu to veľmi nepomohlo lebo je tam len ID k session toho hesla a nie heslo samotné (pritom sa zakaždým vygeneruje heslo nové)

Osobné údaje
Captcha
Odpíšte text z obrázku. Rozlišujú sa malé a veľké písmená.
Obsah
Možnosti