Captcha als Spamschutz mit PHP erstellen

Author: Ing. Michael Fürst (office@bluegate.at)
Web: http://www.bluegate.at
Publiziert: Juli 2008
Bei diesem Tutorial handelt es sich um eine modifizierte (objektorientierte) Version des Tutorials auf stoppt-den-spam.info.

Einleitung und Hinweise

Um dieses Tutorial bzw. die fertigen Klassen nützen zu können, muss Ihr System folgende Anforderungen erfüllen:

Download

Hier können Sie ein komplettes ZIP Archiv mit allen nötigen Klassen und Dateien herunterladen (ready to run):

Download bluegate Captcha (bluegateCaptcha_1_00.zip)

Wozu ein Captcha?

Häufig kommt es vor, dass sogenannte "Bots" Formulare von Websiten automatisiert ausfüllen (z.B. Registrierungs- oder Kontaktformulare). Das führt dazu, dass Sie als Seitenbetreiber keine realen Daten sondern nur maschinell erzeugten Spam erhalten. Dieses Problem tritt vor allem bei Open-Source Software auf, die weltweit sehr häufig eingesetzt wird (spezialisierte Bots).

Ein simpler Trick vermindert dieses Problem: Das Captcha

Um diesen Problem Herr zu werden bedient man sich der Tatsache, dass es einer Maschine sehr schwer fällt, Bilder zu deuten bzw. zu lesen. Man führt bei einem Webformular ein Bild mit relativ schwer lesbarer Schrift an und bittet den User den dort dargestellten Text in ein dafür vorgesehenes Textfeld einzugeben (Siehe Bild "Anwendungsbeispiel"). Stimmen die Daten im Feld mit jenen des Bildes überein, wird das Formular akzeptiert. Nachdem eine Maschine das Bild bzw. den enthaltenen Text nur sehr schwer auslesen kann, sind die Bots nahezu chancenlos.

Beispiel für ein Captcha:

Anwendungsbeispiel: Registrierung in einem Forum:

 

Captcha-Hintergrundbilder

Als Hintergrundbild verwenden wir PNG Dateien in einer Größe von 140x40 Pixel. Sie können beliebig viele Hintergründe für das Captcha selbstständig erstellen und in das Captcha integrieren (z.B.: mit Paint oder Photoshop). Achten Sie nur darauf, dass das Bild über mehrere "Störungen" (Körnung, Farbwechsel, Linien etc.) verfügt. Das erschwert das maschinelle Auslesen des Captchas. Bei der Download-Version (siehe Seitenanfang) sind bereits drei verschiedene Hintergrundbilder enthalten.

Captcha PHP Klasse (class.captcha.php)

Auf Basis der Captcha Funktion auf http://www.stoppt-den-spam.info habe ich eine Klasse entwickelt, die alle nötigen Funktionen zum Erstellen eines Captchas in PHP bereitstellt.

class.captcha.php - Captcha PHP Klasse
  1. /*
  2. * Klasse "Captcha"
  3. * Erzeugt ein Objekt das ein Captcha für den Schutz vor automatisierten
  4. * Anmeldungen ausliefert
  5. *
  6. * Anforderungen: >= PHP 4, GD Lib
  7. * (c) 2008 bluegate communications, Ing. Michael Fürst
  8. * Web: http://www.bluegate.at
  9. *
  10. * Basierend auf der Captcha Entwicklung von stoppt-den-spam.info
  11. */
  12.  
  13. class Captcha {
  14.  
  15. var $captchaText='';
  16. var $bgImage='';
  17. var $captchaFont='XFILES.TTF';
  18. var $captchaFontSize=25;
  19. var $captchaTempImagePath = '/captcha/tempimages/';
  20. var $minAngle = 0;
  21. var $maxAngle = 5;
  22. var $deleteTimeDiff = 10;
  23.  
  24. function Captcha() {
  25. return true;
  26. }
  27.  
  28. /*
  29. * Erzeugen eines Zufallstextes für das Captcha
  30. */
  31. function setCaptchaText($textLength,$possibleSigns) {
  32.  
  33. srand($this->getSeed());
  34.  
  35. while(strlen($this->captchaText)<$textLength) {
  36. $this->captchaText.=substr($possibleSigns,(rand()%(strlen($possibleSigns))),1);
  37. }
  38.  
  39. }
  40.  
  41. /*
  42. * Liefert den Captchatext zurück
  43. */
  44. function getCaptchaText() {
  45. return $this->captchaText;
  46. }
  47.  
  48. /*
  49. * Seed der Zufallszahlen
  50. */
  51. function getSeed() {
  52. list($usec , $sec) = explode (' ', microtime());
  53. return (float) $sec + ((float) $usec * 100000);
  54. }
  55.  
  56. /*
  57. * Festlegen des Hintergrundbildes, erwartet Array mit verschiedenen Elementen
  58. */
  59. function setBgImage($imageArray) {
  60. $this->bgImage = $imageArray[array_rand($imageArray,1)];
  61. }
  62.  
  63. /*
  64. * Festlegen des Fonts
  65. */
  66. function setFont($fontPath) {
  67. $this->captchaFont = $fontPath;
  68. }
  69.  
  70. /*
  71. * Setzen der Schriftgröße
  72. */
  73. function setFontSize($fontSize) {
  74. $this->captchaFontSize = $fontSize;
  75. }
  76.  
  77. /*
  78. * Setzen des Neigungswinkels
  79. */
  80. function setAngle($minAngle, $maxAngle) {
  81. $this->minAngle = $minAngle;
  82. $this->maxAngle = $maxAngle;
  83. }
  84.  
  85. /*
  86. * Setzt den Pfad zum Temporären Captcha Image fest
  87. */
  88. function setCaptchaTempImagePath($captchaTempImagePath) {
  89.  
  90. $this->captchaTempImagePath = $captchaTempImagePath;
  91.  
  92. }
  93.  
  94. /*
  95. * Erstellt das Captcha Image und liefert es zurück
  96. */
  97. function getCaptchaImage() {
  98.  
  99. // Background Image definieren
  100. $img = ImageCreateFromPNG($_SERVER['DOCUMENT_ROOT'].$this->bgImage);
  101. // Schriftart und Farbe definieren
  102. $color = ImageColorAllocate($img, 0, 0, 0);
  103. $ttf = $_SERVER['DOCUMENT_ROOT'].$this->captchaFont;
  104. $ttfsize = $this->captchaFontSize;
  105. // Neigungswinkel & Abstände
  106. $angle = rand($this->minAngle,$this->maxAngle);
  107. $t_x = rand(5,30);
  108. $t_y = 35;
  109.  
  110. // Temp-Dateiname für die Ausgabe des Captchas
  111. $imageTempFilename = mktime() . '_'.md5(microtime()).'.png';
  112.  
  113. // Text und BG Image mergen und PNG erstellen
  114. imagettftext($img, $ttfsize, $angle, $t_x, $t_y, $color, $ttf, $this->captchaText);
  115. imagepng($img,$_SERVER['DOCUMENT_ROOT'].$this->captchaTempImagePath.$imageTempFilename);
  116.  
  117. // PNG mit <img> wrappen
  118. $output = '<img src="'.$this->captchaTempImagePath.$imageTempFilename.'" />';
  119. imagedestroy($img);
  120.  
  121. return $output;
  122. }
  123. /*
  124. * Legt fest, nach wievielen Sekunden ein temporäres Captcha Image gelöscht werden darf
  125. */
  126. function setDeleteTimeDifference($deleteTimeDiff) {
  127. $this->deleteTimeDiff = $deleteTimeDiff;
  128. }
  129. /*
  130. * Löscht die temporären Captcha Images
  131. * Gelöscht werden alle Images, die älter als 60 Sekunden sind.
  132. */
  133. function cleanUpCaptchaTempImages() {
  134. $strDir = $_SERVER['DOCUMENT_ROOT'].$this->captchaTempImagePath;
  135.  
  136. $oDir = dir( $strDir );
  137.  
  138. while ( false !== ( $strFile = $oDir->read () ) )
  139. {
  140. if ( $strFile != '.' && $strFile != '..' && ! is_link ( $strDir . $strFile ) && is_file ( $strDir . $strFile ) )
  141. {
  142. // Alter des Files (in Sekunden) ermitteln
  143. $fileTimeStamp = substr($strFile,0,strpos($strFile,'_'));
  144. $fileAge = mktime() - $fileTimeStamp;
  145. // File löschen, wenn es älter ist als $deleteTimeDiff Sekunden
  146. if ($fileAge > $this->deleteTimeDiff) {
  147. @ unlink ( $strDir . $strFile );
  148. }
  149. }
  150. }
  151.  
  152. $oDir->close();
  153.  
  154. }
  155.  
  156. }

Erstellen des Captchas (Objektinstanz - index.php)

Mit nachfolgenden Zeilen können Sie nun einfach eine Instanz des Captcha-Objekts erstellen und das Captcha Image ausliefern. Weiters stehen eine Vielzahl von Konfigurationsmöglichkeiten zur Verfügung.

index.php - Captcha Objekt instanzieren
  1. /*
  2. * bluegate "Captcha"
  3. * Erzeugt ein Captcha für den Schutz vor automatisierten Anmeldungen
  4. *
  5. * Anforderungen: >= PHP 4, GD Lib
  6. * (c) 2008 bluegate communications, Ing. Michael Fürst
  7. * Web: http://www.bluegate.at
  8. *
  9. * Basierend auf der Captcha Entwicklung von stoppt-den-spam.info
  10. */
  11.  
  12. /* Include required Classes and create Object*/
  13. require('class.captcha.php');
  14. $captcha = new Captcha();
  15.  
  16. /* Konfiguration */
  17. $captcha->setCaptchaText(5,'ABCDEFGHJKLMNPRSTUVWXYZ23456789');
  18. $captcha->setBgImage(array('/captcha/captcha_1.png','/captcha/captcha_2.png','/captcha/captcha_3.png'));
  19. $captcha->setFont('/captcha/XFILES.TTF');
  20. $captcha->setFontSize(25);
  21. $captcha->setAngle(0, 3);
  22. $captcha->setCaptchaTempImagePath('/captcha/tempimages/');
  23. $captcha->setDeleteTimeDifference(5);
  24.  
  25. /* Image ausgeben */
  26. echo $captcha->getCaptchaImage();
  27.  
  28. /* Temporäre Files löschen */
  29. $captcha->cleanUpCaptchaTempImages();
  30.  
  31. /* Ausgabe des Captcha als Plain Text (für Compare) */
  32. echo $captcha->getCaptchaText();

Ein Zip Archiv mit allen nötigen Dateien können Sie am Beginn dieser Seite herunterladen.

Konfigurationsparameter & Methoden

  • setCaptchaText($textLength,$possibleSigns)
    Legt die Zeichenlänge sowie die erlaubten Zeichen im Captchatext fest

  • getCaptchaText()
    Liefert den Captchatext im Plain Text Format zurück (für Vergleiche)

  • setBgImage($imageArray)
    Erwartet ein Array mit Bildpfaden für die Hintergrundbilder des Captchas

  • setFont($fontPath)
    Pfad zu einem TTF Font, aus dem der Text gebildet werden soll

  • setFontSize($fontSize)
    Schriftgröße in Pixel

  • setAngle($minAngle, $maxAngle)
    Minimaler und Maximaler Neigungswinkel des Textes in Grad

  • setCaptchaTempImagePath($captchaTempImagePath)
    Pfad zu einem Verzeichnis, in dem die Temporären Captcha Bilddaten gespeichert werden können

  • getCaptchaImage()
    Liefert das Captcha-Bild mit einem <img> Wrap zurück

  • setDeleteTimeDifference($deleteTimeDiff)
    Legt die Zeitspanne in Sekunden fest, die ein temporäres Captcha-Bild mindestens alt sein muss, bevor es gelöscht werden kann

  • cleanUpCaptchaTempImages()
    Leert den Order mit den temporären Captcha-Bildern (abhänging von der mittels setDeleteTimeDifference($deleteTimeDiff) gesetzten Alters-Zeitspanne )