PHP ellenőrzőkód - R.E. Captcha v1.0

Captcha kép 1

Captcha kép 2

Újabb taggal bővült az "R.E. termékcsalád", (R.E. mint RimElek) mert hogy már szinte védjegyem. Ezúttal egy Captcha PHP osztály személyében. Itt bal oldalt található is két példa kép. Mint látható, az egyiken egy matematikai műveletet kell elvégezni, a másikon pedig csak felismerni a véletlenszerűen megjelenített karaktersorozatot. Mindkét esetben megzavarva a képet a szintén véletlenszerűen generálható vonalakkal.


R.E. Captcha v1.0 letöltése
R.E. Captcha v1.0.1 letöltése
Dokumentáció letöltése
Dokumentáció online megtekintése

A fent említett két mód között már mondanom sem kell, hogy hogyan vált a program. Természetesen véletlenszerűen. Persze nem csak fix betűtípussal használható. Tetszés szerint megadható bármilyen ttf betűtípus fájl. Állítható a betűméret, a kép méret és a kép típusa is. ( jpg, png, gif ) Ezen kívül a háttérszín is, bár leginkább világos háttérszín mellett mutat jól tapasztalataim szerint. Még érdekesség, hogy mivel gyakran fordultak hozzám oylan kérdéssel, hogy egy PHP-val generált képet hogyan lehet megjeleníteni egy html fájlban, így két megjelenítési lehetőséget is beépítettem.

  • Kép típusú php fájlban:
    Ez annyit jelent, hogy egy üres php fájlt kell nyitni, és abba csakis kizárólag a kép létrehozást tenni. Megadva a megfelelő Content-type fejlécet a header() függvénnyel. Majd ezt a fájlt egyszerűen úgy tekinteni, mintha egy jpg, png vagy gif kép lenne. Azaz ugyanúgy be lehet írni html-ben egy img tag-be.

  • Közvetlenül img tag-ben:
    Ezzel a megoldással nincs szükség új php fájlra, hanem egy base64 algoritmussal kódolt kép forráskód kerül bele közvetlenül az img tag-be. Lehetőség tehát van rá, bár én az első megoldást jobban preferálom.

Példák
Példák nélkül mit sem ér egy program leírás. Tehát a fent említett két lehetőségre álljon itt most két példa, ami a dokumentációban is megtalálható.

1. verzió. Kép típusú fájlként
Csak az RECaptcha osztályra van szükség. Ez után példányosítani kell a konstruktorban tömbként átadott opciók megadásával. Végül a flush() metódussal kiküldeni a legenerált képet a képernyőre.

<?php
/*
 * Példa Captcha létrehozására kép típusú php fájlban
 */

require_once 'RECaptcha/RECaptcha.class.php';
//kép létrehozás
$captcha = new RECaptcha(array(
                'fonttype' => '../fonts/arial.ttf', //Ez az alapértelmezett is
                'fontsize' => '10',
                'bgcolor' => '170,255,200',
                'bgintensity' => 2,
                'fgintensity' => 3,
                'height' => '50',
                'width' => '100',
                'spacerange' => array(1,2)
                ));
$captcha->flush();

?>

Ezt a kódot kipróbálva egy arial betűtípusú, 10-es betűmérettel rendelkező (170, 255, 200) RGB összetevőjű háttérrel rendelkező kép jön létre. A képet a megjelenő szöveg előtt és után véletlenszerű zavaró vonalak torzítják, aminek intenzitását az fgintensity ( szöveg előtti ) és bgintensity (szöveg mögött) opciók adják meg. A kép 100 pixel széles és 50 pixel magas. A karakterek között pedig minim 1, és maximum 2 pixel térköz lehet. html forráskódba beillesztése:
<img src="captcha.php" alt="ellenőrző kód" />

2. példa. Közvetlen beágyazás html img tag-be:

<?php
/*
 * Példa Captcha létrehozására html kódba ágyazva
 */

require_once 'RECaptcha/RECaptcha.class.php';
//kép létrehozás
$captcha = new RECaptcha(array(
                'fonttype' => 'fonts/arial.ttf', //Ez az alapértelmezett is
                'fontsize' => 10,
                'bgcolor' => '170,255,200',
                'bgintensity' => 2,
                'fgintensity' => 3,
                'height' => '50',
                'width' => '100',
                'spacerange' => array(1,2),
                'params' => array(
                        'style'=>'width: 300px;'
                        )
                ));
print $captcha;

?>

Ez a kép az előző példához hasonló paraméterekkel rendelkezik. Kiegészítve azzal, hogy a params opcióban megadható az img tag-ben használni kívánt új attribútumok listája. Én csak a style attribútumot használtam, amivel a kép szélességét növeltem meg. Természetesen nem életszerű példa, hisz ki akarná ronda pixelesen látni a captcha képét. Még említést érdemel, hogy itt csak simán print utasítással kellett kiírni a captcha-t, mert tartalmaz az osztály egy __toString metódust, ami ebben az esetben html forráskóddá konvertálja a képet.

Mindkét esetben a captca által generált képre adandó válasz alapértelmezetten egy $_SESSION['captcha_code'] nevű session változóba kerül. Ez felülbírálható szintén a konstruktorban megadott 'session_name' opcióval. Ez után már csak össze kell hasonlítani ezt az értéket egy űrlapon elküldött értékkel. Nyilván még mielőtt azt a captcha újra felülírná.

Végezetül egy példakód a vizsgálatra kép típusú fájl esetén:

<?php
if (isset ($_POST['code']) )
{
     if (strtolower($_POST['code']) == $_SESSION['captcha_code'])
     {
          print "Helyes kódot adtál meg!";
     }
     else
     {
          print "Ez nem talált!";
     }
}
?>
<form action="" method="post">
<img src="captcha.php" /><br />
Ellenőrzőkód: <input type="text" name="code" />
<input type="submit" value="Ellenőrzés" />
</form>

És példa base64 formátumú kép esetén:

<?php
$captcha = new RECaptcha(array(
                'fonttype' => 'fonts/arial.ttf', //Ez az alapértelmezett is
                'fontsize' => 10,
                'bgcolor' => '170,255,200',
                'bgintensity' => 2,
                'fgintensity' => 3,
                'height' => '50',
                'width' => '100',
                'spacerange' => array(1,2),
                'params' => array(
                        'style'=>'width: 300px;'
                        )
                ));

if (isset ($_POST['code']) )
{
     if (strtolower($_POST['code']) == $_SESSION['captcha_code'])
     {
          print "Helyes kódot adtál meg!";
     }
     else
     {
          print "Ez nem talált!";
     }
}
?>
<form action="" method="post">
<?php print $captcha ?><br />
Ellenőrzőkód: <input type="text" name="code" />
<input type="submit" value="Ellenőrzés" />
</form>

Természetesen mind két verzió feltételezi, hogy a session el van indítva megfelelően a kép létrehozásánál és az ellenőrzésnél is.

Szerkesztve: 2011. június 27.
A v1.0.1 -es verzió csak egy javított változat az 1.0 -hoz. A javítás oka: A freeweb.hu ingyenes tárhelyszolgáltatón nem jelentek meg a betűk a képen.
A Hiba oka: A freeweben valamiért be kellett írni egy olyan sort a programba, ami gyakorlatilag nem csinál semmit. A jelenség előtt értetlenül állok, de valószínűleg a szolgáltató is, mert az erre vonatkozó, pontosan megfogalmazott, forráskóddal ellátott hibajelentésemre és egyben kérdésemre nem válaszoltak lassan két hete. A beillesztett sor a következő:

/*
 * freeweb.hu szolgáltató miatt került be ez a sor. E nélkül
 * ott nem jelennek meg a truetype fontok.
 */

imagettftext($this->source, 0, 0, 0, 0, 0, $this->fonttype, '');

Aki nem akarja letölteni az új verziót, az másolja be az 1.0 -ban a fenti sorokat a következő rész után:

protected function codeGenerator($fontsize)
{
        if (!file_exists($this->fonttype))
        {
                exit('<b>'.$this->fonttype.'</b> not found!');
        }
Kategóriák: 
Megosztás/Mentés

Hozzászólások

izzsi képe

Hali
Van hír scriptem amibe behívtam egy hir_komment.php-t és az hogy tudom működésre bírni a captcha-t az sql beírásnál?
<?php session_start(); require_once 'RECaptcha.class.php'; $captcha = new RECaptcha(array('fonttype' => 'files/arial.ttf',));?>

<form method="post" name="beir" action="<? $_SERVER[PHP_SELF] ?>" onSubmit="return checkform_gb(this)"/>
<p><label for="nev">Neved:</label><br><input type="text" name="nev" id="nev" value="" size="36" /><br>
<label for="email">Email:</label><br><input type="text" name="email" id="email" value="" size="36" /><br>
<label for="uzenet">Üzenet:</label><br><textarea name="uzenet" id="uzenet" rows="10" cols="36" /></textarea><br />

<?php print $captcha ?>

<br />
Ellenőrzőkód: <input type="text" name="code" /><br />
<input type="submit" name="mehet" value="     Küldés     " id="egy" /></p></form>
<?php if(isset($_POST['mehet'])){
if($_POST['nev'] !=="" && $_POST['email']!=="" && $_POST['uzenet'] !=="" ){
$nick = htmlspecialchars($_POST['nev']);
$email = htmlspecialchars($_POST['email']);
$uzenet= nl2br(htmlspecialchars($_POST['uzenet']));
$datum = date('Y.m.d. H:i:s',time()+21600);
$sql = "INSERT INTO hir_komment (`kid` , `hid` , `nev` , `email` , `komment` , `datum` ) VALUES ( '' , '$id', '".$nick."', 'mailto:".$email."', '".$uzenet."', '".$datum."')";
if($query = mysql_query($sql)){ print "<p>Hozzászólásodat rögzítettük, moderálás után megjelenik!</p>"; } else{echo mysql_error();}}} ?>
<?php
if (isset ($_POST['code']) )
{
     if ($_POST['code'] == $_SESSION['captcha_code'])
     {
          print "Helyes kódot adtál meg!"; <- ide kéne jönni az sql beírásnak?
     }
     else
     {
          print "Ez nem talált!";
     }
}
?>

A kép megjelenik, de mindig a nem találtat írja ki.

Rimelek képe

Most nem tudom mi a gond. De írd ki a session és a post értékét is var_dump() -pal. Akkor látod, ha egyik vagy másik szóközt tartalmaz. És hogy van-e kis/nagy betű különbség. És ha igen, akkor az strtolower függvényt kell használnod mindkettőre.

Viszont ennek:
<? $_SERVER[PHP_SELF] ?>
semmi értelme. És hibás is. Nincs kiírva tehát nem csinál semmit a kód. Így lenne jó:
<?php echo $_SERVER['PHP_SELF'] ?>

Anonymous képe

Tökéletesen működik és használom is. De nálam mindig "ez nem talált" eredményt ad ha az ellenőrző kódba van nagybetű amit persze én is nagybetűvel adok meg.
Erre módosítva már működik helyesen.

if (strtolower($_POST['code']) == strtolower($_SESSION['captcha_code']))

Rimelek képe

Jogos észrevétel, köszönöm!

De elég az elküldött értéket konvertálni. A session-be már kisbetűvel kerülnek a karakterek, ezért is volt a probléma. Javítottam a példát a bejegyzésben is így 5 év után :)

Anonymous képe

Sokat segített a kód, de egy pici hiba csúszott a "példakód a vizsgálatra kép típusú fájl esetén:" 2015-ös javításába (4. sor):
if (strtolower($_POST['code')] == $_SESSION['captcha_code'])
a helyes
if (strtolower($_POST['code']) == $_SESSION['captcha_code'])

Rimelek képe

Köszönöm a hibajelentést! Javítva.

Anonymous képe

kicsit nagyobbra kellene állítani a capctha betű méretét, mert a kapcsolatban kb tizedikre sikerült eltalálni, hogy mi is van a képen. Lehet itt is így járok.

Rimelek képe

Ha a bejegyzés tetején levő képhez hasonló méretben látod a betűket, szerintem az még olvasható. Akkor szokott kicsi lenni azt hiszem, ha hiányznak a PHP-ból a TrueType betűtípusok. De majd ha odajutok, lehet újraírom ezt is. Egyelőre más van soron. De köszönöm az észrevételt így igen csak megkésett válaszban is.

Új hozzászólás