[Tutorial] [PHP-Tutorial] Captchas generieren und überprüfen

Dieses Thema im Forum "Webentwicklung" wurde erstellt von teqnix, 27. Februar 2009 .

Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 27. Februar 2009
    Zuletzt von einem Moderator bearbeitet: 14. April 2017
    [PHP-Tutorial] Captchas generieren und überprüfen

    Captchas generieren und überprüfen

    Bild Bild Bild

    Hallo zu meinem ersten PHP-Tutorial. Ich hoffe, dass ich es einigermaßen verständlich erklärt habe

    Vorraussetzungen
    • Grundwissen in PHP und der GD Library
    • PHP fähigen Webspace
    • GD

    Der Code
    captcha.php
    Wir fangen mit der Datei an, die später unser Captcha ausgeben soll (captcha.php).
    Als erstes müssen wir folgendes in die Datei schreiben:
    PHP:
    session_start ();
    mt_srand ( microtime () *  1000000 );
    Diese Funktionen sollten bekannt sein.

    Danach müssen wir uns eine Funktion zur Erstellung einer zufälligen Zeichenkette basteln.
    Es gibt hier mehrere Möglichkeiten, ich habe diese genommen:
    PHP:
    function  RandomString ( $length = 4 , $chars = 'abcdefghijklmnpqrstuvwxyz' ){
        
    $result  '' ;
        for(
    $i = 0 ; $i < $length ; $i ++) {  $result  .=  $chars [ mt_rand ( 0 , strlen ( $chars )- 1 )]; }
        return 
    $result ;
    }
    Der Code sollte für euch selbsterklärend sein.

    Jetzt kommen wir zum spannenden Teil: Erstellen des Bildes
    Wir beginnen damit, dass wir einen Salt und den Captchacode generieren:
    PHP:
    $salt  RandomString ( mt_rand ( 0 , 9 ). mt_rand ( 0 , 9 )); 
    $code  RandomString ( 5 );
    Wir verwenden hierbei unsere RandomString Funktion, die wir zuvor erstellt haben.
    Danach speichern wir beide in Sessions.
    PHP:
    $_SESSION [ 'salt_code' ]     =  $salt ;
    $_SESSION [ 'security_code' ] =  md5 ( $code . $salt );
    Der Code wird nicht im Klartext gespeichert, sondern wir speichern die MD5 -Summe von dem Code und unserem Salt.

    Danach erfolgen Überprüfungen, ob uns ein Code übergeben wurde, und ob wir das Modul GD laden können.
    PHP:
    if(empty( $_SESSION [ 'security_code' ])) { die( 'Kein Captchacode vorhanden' ); }
    if(!
    extension_loaded ( 'gd' )) { die( 'GD Library nicht vorhanden' ); }
    PHP:
    $captcha           imagecreate ( 100 , 35 ) OR die( 'Konnte Captcha nicht erstellen' );
    $color_background  imagecolorallocate ( $captcha 255 255 255 );
    $color_text        imagecolorallocate ( $captcha 0 0 0 );
    $text              $code ;
    Erklärung:
    mit imagecreate erstellen wir ein leeres Bild 100px x 35px. Sollte dies nicht funktionieren, wird eine entsprechende Fehlermeldung ausgegeben.
    In $color_background setzen wir mittels imagecolorallocate die Hintergrundfarbe des Bildes, und in $color_text dementsprechend die Farbe der Schrift.
    $text ist unser Text, der später auf den Bild steht.
    Danach "füllen" wir unser bis jetzt leeres Bild mit der Hintergrundfarbe auf.
    PHP:
    imagefill ( $captcha 0 0 $color_background );
    Jetzt setzen wir den zuvor generierten Text auf unser Bild; das Besondere: er ist nicht statisch, d.h. die einzelnden Buchstaben verändern bei jedem Aufruf ihre X- und Y-Werte.
    PHP:
    $i_x  mt_rand ( 3 , 15 );
        for(
    $i = 0 ; $i < strlen ( $text ); $i ++) {
            
    $i_y  mt_rand ( 1 , 20 );
            
    imagestring  ( $captcha mt_rand ( 4 , 6 ),  $i_x $i_y $text [ $i ],  $color_text );
            
    $i_x  +=  mt_rand ( 15 , 20 );
    }
    Der Code macht folgendes: in $i_x wird zunächst ein zufälliger Wert zwischen 3 und 15 gespeichert. Danach werden in einer for-Schleife die einzelnden Buchstaben aus dem String $text mittels imagestring auf das Bild gezeichnet. Außerdem werden bei jeden Durchlauf die X- und Y-Werte geändert (X wird immer um einen Wert zwischen 15 und 20 inkrementier; Y wird ein zufälligen Wert zwischen 1 und 20 zugewiesen).

    Soweit, sogut. Jetzt müssen wir das Bild nur noch ausgeben und das funktioniert so:
    PHP:
    if( function_exists ( 'imagegif' )) {
       
    header ( 'Content-type: image/gif' );
       
    imagegif ( $captcha );
    } elseif (
    function_exists ( 'imagepng' )) {
       
    header ( 'Content-type: image/png' );
       
    imagepng ( $captcha );
    } elseif (
    function_exists ( 'imagejpeg' )) {
       
    header ( 'Content-type: image/jpeg' );
       
    imagejpeg ( $captcha '' 0.5 );
    } else { 
        die(
    'Grafikunterst&uuml;tzung nicht gefunden' ); 
    }
    Wir überprüfen, ob die unsere gewünschte(n) Funktion(en) zum ausgeben des Bildes exestieren. Je nachdem, welche genommen wird, wird mittels header der Content-type angepasst und dann mit der Funktion das Bild ausgegeben.

    Zu guter Letzt geben wir das Bild im Speicher mit imagedestroy frei.
    PHP:
    imagedestroy ( $captcha );
    Einbau in ein Formular (Beispiel)
    form.php
    Der Einbau ist relativ einfach:
    Einbinden des Bildes erfolgt einfach mit
    HTML:
    <img src="captcha.php" border="0"/>
    .
    Prüfung:
    PHP:
    if(isset( $_POST [ 'captcha_code' ])) {
        
    $salt  =   $_SESSION [ 'salt_code' ];
         unset(
    $_SESSION [ 'salt_code' ]);
        if(
    md5 ( $_POST [ 'captcha_code' ]. $salt ) ==  $_SESSION [ 'security_code' ]) {
            echo 
    '<b>O Der Code war korrekt</b>' ;
            
    // weiteres script....
        
    } else {
            echo 
    '<b>X Der Code war falsch</b>' ;
            
    // weiteres script....
        
    }
    }
    Die Prüfung erfolgt mit if(md5($_POST['captcha_code'].$salt) == $_SESSION['security_code']).
    Wir überprüfen, ob der vom User eingegebene Code aus dem Formular mit dem vom Bild übereinstimmt.
    Da unsere Session security_code nur die MD5 -Summe des richtigen Codes und des Salts enthält ist, müssen wir auch die MD5 -Summe von der Eingabe des Users und unseres Salts errechnen (md5($_POST['captcha_code'].$salt). Dies wird dann einfach mit der Summe in der Session security_code abgeglichen.
    Wichtig ist, dass die Session salt gelöscht (hier mittels unset ) oder verändert wird!

    Anmerkung
    Diese Captchas sind nicht die besten, und können mit den meisten AC Programmen leicht geknackt werden. Ihr könnt aber mit den GD-Funktionen rumspielen, und z.B. die Schriftart und die Farben ändern und Objekte wie Ellipsen oder Rechtecke ins Bild einfügen.
    Mehr dazu hier.

    Quelltexte
    captcha.php
    Spoiler
    PHP:
    <? php
        session_start
    ();
        
    mt_srand ( microtime () *  1000000 );
        
        function 
    RandomString ( $length = 4 , $chars = 'abcdefghijklmnpqrstuvwxyz' ){
            
    $result  '' ;
            for(
    $i = 0 ; $i < $length ; $i ++) {  $result  .=  $chars [ mt_rand ( 0 , strlen ( $chars )- 1 )]; }
            return 
    $result ;
        }
        
        
    $salt  RandomString ( mt_rand ( 0 , 9 ). mt_rand ( 0 , 9 )); 
        
    $code  RandomString ( 5 );
        
    $_SESSION [ 'salt_code' ]     =  $salt ;
        
    $_SESSION [ 'security_code' ] =  md5 ( $code . $salt );
        
        if(empty(
    $_SESSION [ 'security_code' ])) { die( 'Kein Captchacode vorhanden' ); }
        if(!
    extension_loaded ( 'gd' )) { die( 'GD Library nicht vorhanden' ); }
        
        
    $captcha           imagecreate ( 100 , 35 ) OR die( 'Konnte Captcha nicht erstellen' );
        
    $color_background  imagecolorallocate ( $captcha 255 255 255 );
        
    $color_text        imagecolorallocate ( $captcha 0 0 0 );
        
    $text              $code ;
        
        
    imagefill ( $captcha 0 0 $color_background );
        
        
    $i_x  mt_rand ( 3 , 15 );
        for(
    $i = 0 ; $i < strlen ( $text ); $i ++) {
            
    $i_y  mt_rand ( 1 , 20 );
            
    imagestring  ( $captcha mt_rand ( 4 , 6 ),  $i_x $i_y $text [ $i ],  $color_text );
            
    $i_x  +=  mt_rand ( 15 , 20 );
        }
        
        if(
    function_exists ( 'imagegif' )) {
           
    header ( 'Content-type: image/gif' );
           
    imagegif ( $captcha );
        } elseif (
    function_exists ( 'imagepng' )) {
           
    header ( 'Content-type: image/png' );
           
    imagepng ( $captcha );
        } elseif (
    function_exists ( 'imagejpeg' )) {
           
    header ( 'Content-type: image/jpeg' );
           
    imagejpeg ( $captcha '' 0.5 );
        } else { 
            die(
    'Grafikunterst&uuml;tzung nicht gefunden' ); 
        }
        
    imagedestroy ( $captcha );
    ?>

    form.php
    Spoiler
    PHP:
    <? php
        

        
    session_start ();
        require_once(
    'functions.php' );
        
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
    <html>
    <head>
    <title></title>
    </head>
    <body>
    <img src="captcha.php?<?php  echo  strip_tags ( SID );  ?>" border="0"/>
    <form action="?" method="POST">
    <input type="hidden" name="<?php  echo  strip_tags ( session_name ());  ?>" value="<?php  echo  strip_tags ( session_id ());  ?>">
    <input type="text" name="captcha_code" value="">
    <input type="submit" name="submit">
    </form>
    <br>
    <?php
        
    if(isset( $_POST [ 'captcha_code' ])) {
            
    $salt  =   $_SESSION [ 'salt_code' ];
             unset(
    $_SESSION [ 'salt_code' ]);
            if(
    md5 ( $_POST [ 'captcha_code' ]. $salt ) ==  $_SESSION [ 'security_code' ]) {
                echo 
    '<b>O Der Code war korrekt</b>' ;
                
    // weiteres script....
            
    } else {
                echo 
    '<b>X Der Code war falsch</b>' ;
                
    // weiteres script....
            
    }
        }
    ?>
    </body>
    </html>
     
  2. 1. März 2009
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Hey,

    sehr schön gemacht Werde das gleich morgen mal ausprobieren

    Dickes THX und BW is raus



    Gruß Blackbird89
     
  3. 22. Mai 2010
    Zuletzt von einem Moderator bearbeitet: 14. April 2017
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Hallo,

    danke erst mal für das Tutorial!

    habe versucht es in mein bestehendes Gästebuch zu übernehmen und etwas anzupassen.

    Das Anzeigen des Bildes funktioniert schon mal, allerdings erkennt er den eingegebenen Code nie als richtig an.

    Ich vermute es liegt daran, dass $_SESSION['security_code'] und $_SESSION['salt_code'] immer leer sind wenn ich sie mit echo auf der Seite ausgebe.

    Könnte es ein Session Problem sein? Hab nun auf der Guestbook Seite am Anfang auch noch ein session_start() eingefügt, aber das Problem besteht immer noch.

    Kenn mich nicht sehr gut mit PHP aus, daher bräuchte ich hier Hilfe.

    Hier noch die guestbook.php und die captcha.php files:

    guestbook.php
    captcha.php
     
  4. 22. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Finde das Tut noch ein wenig verbesserungswürdig. Tutorials sind gerade für PHP Anfänger gedacht. Du setzt schon relativ erfahrung vorraus.

    Wenn ich sowas lese, da kann ich mir auch direkt ein ferties Script runterladen und es mir angucken.. Ist ja alles selbsterklärend. Oder aber Salt ist für mich ne Stufe weiter als Grundwissen über PHP. Manche haben null Plan was das überhaupt ist.

    Wieso ist das wichtig? Du wirfst Sachen in den Raum und erklärst sie dann nicht. Für ein Tut ist das für mich zu wenig.



    @Dimi. Bekommst du auch kein 'header already send....'?
    In deiner guestbook.php ist ein Zeichen vor dem PHP Tag und in der Captchar sind viele Leerzeichen vor dem session_start();

    Spricht für die falsche Speicherung der Datei.
     
  5. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Danke an hacker5,

    es lag wirklich an diesem blöden Zeichen(BOM), dass mir unter Notepad++ nicht angezeigt wird. Ich hatte die guestbook.php im UTF-8 Format gespeichert und hab es jetzt in UTF-8 ohne BOM geändert.

    Die Meldung:
    hatte ich auch bekommen als ich die Datei noch mit BOM gespeichert hatte und die Funktion so eingefügt habe:
    PHP:
    <? php
        session_start
    ();
    ?>
    Die Meldung kam nicht mehr als ich alles zusammengeschrieben hatte. Aber da hat es noch nicht funktioniert.
    Jetzt, ohne das BOM Zeichen kann ich die Funktion auch so wie oben formatiert in der Datei stehen lassen und es funktioniert einwandfrei.

    Zum Tutorial selber:
    Es hätte wirklich etwas mehr erklärt werden können, z.B. wofür dieser salt ist.
    Ich kann mir denken, dass es einfach ein zufallsgenerierter Code ist, der an den CaptchaCode angehängt wird, um die Sicherheit nochmal etwas zu erhöhen.

    Dann noch eine Frage:
    Ich will in den else Block, also wenn ein falscher Code eingegeben wurde noch einbauen, dass die per POST übergebenen Formulardaten wieder in die Formularfelder geschrieben werden. Wie mach ich das am besten? Kann ich da JavaScript in PHP verwenden?
     
  6. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen


    Gib deinen Inputfeldern/Textarea einfach den value von dem POST. Als Beispiel:

    HTML:
    <input type="text" name="name" value="<?php echo $_POST['name'];?>">
    <textarea name="text"><?php echo $_POST['test];?></textarea>
    
    <!--Oder noch genauer gesehen sogar so-->
    
    <input type="text" name="name" 
    value="<?php if(isset($_POST['name'])) ? htmlspecialchars($_POST['name']) : '';?>">
    

    Das ganze nennt sich Affenformular.
     
  7. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Thx noch mal!

    Habs nun doch als javascript eingebaut, damit die Felder im Falle einer korrekten Code Eingabe leer bleiben.

    So siehts nun aus:

    PHP:
    ...

        else {
        // Falscher Code eingegeben
    ?>
        <script language="JavaScript" type="text/javascript">
            document.guestbook.name.value = "<?php  echo  $_POST [ 'name' ?>";
            document.guestbook.mail.value = "<?php  echo  $_POST [ 'mail' ?>";
            document.guestbook.ort.value = "<?php  echo  $_POST [ 'ort' ?>";
            document.guestbook.text.value = "<?php  echo  $_POST [ 'text' ?>";
            alert("Es wurde ein falscher Code eingegeben!\nBitte den korrekten Code eingeben.");
        </script>
    <?php
        
    }
    }
    ...
    Funzt nun alles bestens :]
     
  8. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    wenn javascript ins spielt kommt, dann sollte auch eine alternative vorhanden sein für die die es nicht haben. benutzerfreundlich
    Code:
    <script>
    ....
    </script>
    <noscript>
    Es wurde ein falscher Code eingegeben!<br>
    Bitte den korrekten Code eingeben
    </noscript>
    
     
  9. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    @Dimi -> never trust user input

    verwende min. addslashes oder besser htmlentities [...] und gib niemals user input einfach so aus.

    @funland

    ne meldung: ja; ne alternative: vergiss es.
    wer neben js noch alternativen verwendet hat die letzten 2 jahre verpasst. im grunde reicht ne meldung das man js einschalten soll, ansonsten -> pech.
     
  10. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen


    Danke das endlich mal jemand genauso denkt. Achtest du dann wenn du mit Ajax arbeitest denn trotzdem dadrauf, dass Formulare oder so trotzdem ohne JS verschickbar sind?
     
  11. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    wenn es nach mir geht, setze ich gar kein javascript ein. diese effekte braucht man nicht, da es alles ohne lösbar ist. wenn dann lieber gleich flash
     
  12. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    nein, d.h verschickbar sind sie schon, aber im php-backend werden sie nicht abgearbeitet, weil ich ajax-requests separat abarbeite indem ich den [X-REQUESTED-WITH: XMLHttpRequest]-header abfrage.
    bei der kommunikation setze ich voll und ganz auf json.

    nur das flash bald aussterben wird...
    ich glaub du hast überhaupt keine ahnung was man mit javascript so alles machen kann
     
  13. 23. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Was mit Javascript alles geht? - Chrome Experiments - Home

    Wie die anderen schon sagten, Tutorial für Fortgeschrittene.
     
  14. 24. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    Tzz benutzerunfreundlich! Ich bastel mir die Seite erst im groben ohne JS, dass sie auch so funktioniert und füge danach meine schönen Effekte hinzu. man strukturiert natürlich die seite so, dass es erweiterbar ist, aber meine seiten sind auch ohne js funktionstüchtig. nur halt nicht so schön. ^^
     
  15. 24. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    definiere mal benutzerfreundlich.

    ist es benutzerfreundlich wenn man für jede noch so minimale aktion die komplette seite neu laden muss? ist es benutzerfreundlich wenn man bei formularen erst nach submit gesagt bekommt das was nicht stimmt?

    ich glaub nicht
    man kann eigl. sagen das ne seite erst MIT javascript richtig benutzerfreundlich wird.

    wenn man mal bedenkt, dass sogar handys javascript implementieren und flash teilweiße nicht, dann muss das doch was heißen. javascript = utility, flash = klickibunti.
     
  16. 26. Mai 2010
    AW: [PHP-Tutorial] Captchas generieren und überprüfen

    mein handy kann sowohl JS als auch flash.
    und benutzerfreundlichkeit in dem sinne, dass leute die javascript "aus sicherheitsgründen" (wie auch immer sie darauf kommen ) deaktiviert haben nicht auf einmal vor einer komplett funktionsuntüchtigen seite stehen. es gibt immer kleine randgruppen die sich gegen JS wehren wollen, und das sind potentielle kunden, die ich von meinen seiten nicht ausschliessen will. klar, man kann einfach n text schreiben "pls enable js." aber ich bin ja immerhin der, ja der "gastgeber" sozusagen und will dem besucher der seite es so angenehm wie möglich machen dass er mir auch jeden scheiß abkauft und geld gibt blabla. javascript ist gut.
     
  17. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.