![]() |
Dies ist eine alte Version des Dokuments!
Ziel dieses Tutorial ist das erzeugen eines sogenannten CAPTCHAs. Das Captcha sollte dynamisch mit PHP erzeugt werden und noch bei der Eingabe soll überprüft werden ob der Code stimmt.
Voraussetzungen:
| Kenntnisse: | JS |
| Software: | Webserver\PHP\MySQL |
| Zeitaufwand: | kA Stunden |
| Vorausgesetzte Themen: | erste-schritte |
Zu allererst soll das Backend mit PHP programmiert werden.
Man benötigt dazu eine Datenbank die die verschiedenen aktuell verwendeten Codes abspeichert.
Dazu müssen wir folgende Datenbank erzeugen
| id | INT | Erhöht sich automatisch |
| code | VARCHAR | Dieser enthält den Code zur jeweiligen ID |
| TIMESTAMP | VARCHAR | Um veraltete Codes löschen zu können |
Dazu einfach folgenden SQL-Code in die Konsole oder PHPMyAdmin einfügen.
CREATE TABLE `sightcodes` ( `id` INT( 11 ) NOT NULL AUTO_INCREMENT , `code` VARCHAR( 5 ) NOT NULL , `TIMESTAMP` VARCHAR( 250 ) NOT NULL , PRIMARY KEY ( `id` ) );
Nachdem wir das abgeschlossen haben können wir uns nun dem PHP Script zuwenden.
Die PHP - Scripts erzeugen nun das Bild und überprüfen auch den Code. Dazu erstellen wir zu allererst folgende Dateistruktur.
So nun beginnen wir mit der Datei config.php.
Config.php
<?php //MYSQL Einstellungen define("HOST", "localhost"); //Hostname der MYSQL Datenbank. define("DATABASE", "test"); //Datenbankname in der die Tabelle ist. define("USER", "test"); //Der Benutzername für die Datenbank. define("PASS", "1234"); //Das Passwort für den darüber angegebenen Benutzer //Ende MYSQL Einstellungen ?>
Das hier sollte eigentlich selbsterklärend sein.
So nun kommen wir zur Erzeugung des Bilds. Wir verwenden den Ordner um dem Browser vorzugaukeln es gäbe auch die richtige FileTyp-Extension (gif). Es würde auch bei direktem Aufruf funktionieren. Allerdings ergibt es so ein besseres Bild.
Zu allererst benötigen wir in dem Ordner eine TTF - Schriftart. Aus dieser erzeugen wir dann das Bild. Verwenden Sie eine etwas verschnörkelte Schrift um ein einfaches Lesen durch eine Maschine unmöglich zu machen. Nennen Sie die Schrift font.ttf und legen Sie die Schriftart in den Ordner sichtcode.gif.
Dannach benötigen wir noch ein Hintergrundbild (200×70), dieses kann mit Streifen durchzogen sein oder einfach nur Weiß sein. Je komplizierter das Hintergrundbild desto schwerer wird es zu lesen. Hier muss ein Mittelweg gefunden werden. Wir nennen es bg.gif und legen es in den Ordner sichtcode.gif.
Nun wenden wir uns dem File index.php zu.
Zu allererst beginnen wir das File und fügen config.php ein.
sichtcode.gif/index.php
<?php require ("../config.php");
Dannach setzen wir den Header für ein GIF Bild.
header ("Content-type: image/gif");
Nun beginnen wir mit dem Erzeugen des Bilds. Wir verwenden die PHP Funktion imagefromgif.
$image=imagecreatefromgif("bg.gif");
Wir laden dabei das Hintergrundbild in den Speicher. Auf diesem Bild können wir nun herummalen.
Nun erzeugen wir zwei Arrays mit all den Zeichen die für das Bild verwendet werden dürfen. Passen Sie auf das keine ähnlich aussehenden Buchstaben verwendet werden. Dazu müssen Sie ihr Font File ansehen.
$letters=array("A","a","B","b","D","d","E","e","F","f","G","g","H","h","I","i","J","j","L","l","M","m","N","n","Q","q","R","r","T","t"); $numbers=array(1,2,3,4,5,6,7,8,9,0);
Nun erzeugen wir das Bild mit einer for-Schleife und der Funktion imagettftext. Ausserdem lassen wir noch die Farbe zufällig ändern.
for($a=1; $a <= 5; $a++ ) { if( rand(0,1) == 0) { $c=$letters[array_rand($letters)]; }else{ $c=$numbers[array_rand($numbers)]; } imagettftext($image, rand(30,35), rand(-30,30), 30*$a+10, 50, imagecolorallocate($image,rand(50,250),rand(50,250),rand(50,250)), "./font.ttf", $c ); $code.=$c; }
Da nun auch wir den code nicht mehr lesen können müssen wir diesen umbedingt noch in die Datenbank schreiben. An den Client senden wäre sinnlos denn dann hätte er ja die Daten. Ausserdem setzen wir noch einen Cookie mit der id aus der Datenbank um später zurückzuprüfen.
mysql_connect( HOST, USER, PASS); mysql_select_db(DATABASE); mysql_query("insert into registrationcode (code,timestamp) values ('$code',".time().") "); $d=mysql_fetch_assoc(mysql_query("select id from registrationcode where code='$code' ")); setcookie("regid",$d['id'],time()+60*30,"/"); mysql_query("delete from registrationcode where timestamp < '".(time()-60*30)."'");
Zu allerletzt müssen wir das Bild nun an den Client senden.
imagegif($image); ?>
Und fertig sind wir mit der Bilderzeugung.
Wir wenden uns nun der Überprüfung zu. Dazu dient das File checkcode.php. Zuerst initialisieren wir alles und holen uns den COOKIE vom Benutzer.
<?php require("./config.php"); //Variablen definition $status = "0"; $sql = false; $query = false; $code = false; $id = false; //Ende Variablen definition $id = $_COOKIE[regid];
Nun müssen wir uns mit der MySQL Datenbank verbinden um den richtigen Code herauszufinden.
mysql_connect(HOST,USER,PASS); mysql_select_db(DATABASE); $sql = "Select code from registrationcode where id = '$id'"; $code=mysql_fetch_assoc(mysql_query($sql));
In der Variable $code haben wir nun den aktuellen code.
Nun überprüfen wir das ganze und löschen den Code aus der Datenbank wenn er stimmt. Stimmt er nicht gibt das Script 0 zurück.
if($_GET["code"]==$code["code"]){ $status = 1; mysql_query("delete from registrationcode where id = '$id'"); } else{ $status = 0; } echo $status;
Nun haben wir auch die Überprüfung fertig. Kommen wir zum Frontend.
Wir haben ein File das nennen wir sichtcode.js. Es enthält sämtliche JS - Logik. Zu allererst benötigen wir eine Funktion die das XMLHTTPRequest Objekt erzeugt. Wir nennen die Funktion request().
function request(){ try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){} try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(e){} try{return new XMLHttpRequest();}catch(e){} return false; }
Nun machen wir eine Funktion die den Code überprüft.
function checkcode(){ if(document.getElementById("codeinput").value.length==5){ //document.getElementById("status").innerHTML =' <img alt="Lädt" src="./img/loader.gif" />'; url = "./checkcode.php?code="+document.getElementById("codeinput").value; http_request = request(); if (http_request == false){ alert("Achtung"); } else{ http_request.onreadystatechange = showanswer; http_request.open('GET', url, true); http_request.send(null); } } }
Natürlich wollen wir auch einen neuen Code erzeugen wenn der User den Code nicht lesen kann.
function newSightCode(){ cache = Math.random()*100; document.getElementById("image").src="./sichtcode.gif?cache="+cache; }
Dann haben wir noch eine Funktion die die Antwort ausgibt.
function showanswer(){ var antwort = http_request.responseText; if(antwort == 1){ disable("codeinput",true); document.getElementById("status").innerHTML =' <img alt="Richtige Eingabe" height=16 width=16 src="./img/ok.png" />'; document.getElementById("neu").innerHTML =""; } else if(antwort == 0){ document.getElementById("status").innerHTML = '<img alt="Falsche Eingabe" height=16 width=16 src="./img/false.png" />'; } else if(antwort == 2){ disable("codeinput",true); document.getElementById("status").innerHTMl='Zu oft versucht bitte reloaden Sie die Site. <\ br> Sicher Sie bitte den Inhalt im Messagetextfeld indem Sie ihn kopieren.'; } else{ document.getElementById("status").innerHTMl=antwort; } }
Schlussendlich habe ich mir noch eine einfache Funktion geschrieben um ein Element zu deaktivieren.
function disable(element, dis){ document.getElementById(element).disabled= dis ; }
Nun habe ich natürlich auch eine kurze Testseite für dich.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Live-Sichtcode</title> <script type="text/javascript" src="./sichtcode.js"></script> </head> <body onLoad = 'disable("codeinput", false);'> <img id="image" src="./sichtcode.gif" alt="Sichtcode" /> <input type="text" id="codeinput" maxlength="5" onkeyup="checkcode()" /> <span id="status">Bitte gebe den Sichtcode ein.</span><br /> <a href="javascript: newSightCode()" id="neu">Neuen Sichtcode generieren</a> </body> </html>
Das wars dann einfach einmal ausprobieren.
Um nun das ganze irgendwo zu integrieren muss man natürlich vor der Eintragung der Daten in die Datenbank das ganze nocheinmal überprüfen. Dafür einfach bei checkcode.php das Löschen aus der Datenbank entfernen und folgenden Codeschnippsel bei dir einbauen.
function code($securityid, $eingabe){ //Datenbank öffnen $dblink = openDB(); //Tabelle öffnen $sql = "Select code from registrationcode where id = '$securityid'"; $code=mysql_fetch_assoc(mysql_query($sql)) or die("Fehler mit der Datenbank"); $sql = "delete from registrationcode where timestamp < '".(time()-60*30)."'"; $code=mysql_query($sql) or die("Fehler beim Löschen der alten Codes"); if($eingabe == $code['code']){ $status = 1; mysql_query("delete from registrationcode where id = '$securityid'"); } else { $status = 0; } return $status; }
Auch hier wird wieder ein Status von der Funktion zurückgegeben. Die Funktion openDB muss durch ein Äquivalent ersetzt werden. Ausserdem werden bei diesem Snippet auch alle älteren Codes wieder aus der Datenbank gelöscht.
Natürlich gibt es hier noch einige Modifikationen