[PHP]Closed-Loop Opt-In/Aktivierungslink

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • [PHP]Closed-Loop Opt-In/Aktivierungslink

      Auf Anfrage von My Myner hier ein Tutorial zum Closed-Loop Opt-In(Aktivierungslinks) in PHP

      1. Was ist ein Closed-Loop Opt-In?
      2. Wie realisiere ich einen Closed-Loop Opt-In?


      1. Was ist ein Closed-Loop Opt-In?
      Opt-in ist ein Verfahren um die Zugehörigkeit von z.B. einer E-Mail Adresse zu einer Person zu bestimmen. Das Verfahren kennt jeder aus Foren und sozialen Netzwerken. Bei der Registrierung wird an die angegebene E-Mail Adresse eine Mail mit einem Bestätigungslink geschickt. Dies soll zum einen die Echtheit der Adresse und zum anderen die Zugehörigkeit zu der Person versichen die sich registriert.

      2. Wie realisiere ich einen Closed-Loop Opt-In?
      Wir legen einen neuen User an, erstellen einen Opt-In Schlüssel und schreiben diesen in eine MySql Datenbank.
      Hierfür bietet sich eine Hash Funktion an.

      PHP-Quellcode

      1. <?php
      2. $key = md5($user_id . uniqid ()); //key generieren
      3. //verbindung zur datenbank aufbauen
      4. $link = mysql_connect("localhost", "username", "passwort");
      5. mysql_select_db("datenbank", $link);
      6. //einfügen des keys in die datenbank
      7. mysql_query("INSERT INTO `optin` (`uid`, `userid`, `key`) VALUES (NULL, '" . mysql_real_escape_string($user_id) . "', '" . mysql_real_escape_string($key) . "')", $link);
      8. //senden der mail
      9. mail($email, "Betreff", 'Klicke <a href="http://www.seite.de/optin.php?key=' . $key . '">hier</a>');
      10. ?>
      Alles anzeigen



      Die optin.php

      PHP-Quellcode

      1. <?php
      2. $link = mysql_connect("localhost", "username", "passwort");
      3. mysql_select_db("datenbank", $link);
      4. $result = mysql_query("SELECT * FROM `optin` WHERE `key` = '" . mysql_real_escape_string($_GET["key"]) . "'", $link);
      5. $row = mysql_fetch_assoc($result);
      6. if ($row)
      7. {
      8. //Aktiviere den user anhand der userid
      9. }
      10. ?>
      Alles anzeigen

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von MAP94 ()

    • Mach halt eine abfrage:
      if($_GET['key'] == md5($user_id . uniqid()))
      ...

      was auch immer die uniqid ist...
      ich google mal :33

      //EDIT:
      das mit der uniqid ist müll, das macht für einen zeitpunkt die bestimmte id.
      Wenn du den key nicht iwo speichern willst, musst du ein verfahren entwickeln, der bei jedem acc den gleichen hash ergeben lässt und diesen dann beim freischalten neugenerieren lassen.
      soetwas wie: md5(name . id . ieinzwischenzeug . id . name)
      darfst halt nicht weiter sagen unso.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von schmop ()

    • @MAP94: Ich habe dein Skript angeschaut: es hat zahlreiche Sicherheitslücken. Ein Glück, dass es eh nicht funktioniert (Handle vergessen etc.).
      Beispiel:

      PHP-Quellcode

      1. mysql_query("SELECT * FROM `optin` WHERE `key` = '" . $_GET["key"] . "'");

      Vom User eingegebene Daten ohne Prüfung in eine Query einbauen?? Das lernt man eigentlich am Anfang, dass man das NIEMALS tun sollte! Wenn zum Beispiel $_GET['key'] so aussähe:

      Quellcode

      1. blubb';DROP TABLE 'optin

      dann sähe die Query so aus:

      SQL-Abfrage

      1. SELECT * FROM `optin` WHERE `key` = 'blubb';DROP TABLE 'optin'


      @ My Myner: Wie wärs mit ner Cookie-Lösung?

      PHP-Quellcode

      1. <?php
      2. $key = md5((string)mt_rand(1000000000,9999999999)); // $key ist die MD5-Summe einer zehnstelligen Zufallszahl
      3. setcookie('key',$key,time()+7200,$_SERVER['HTTP_HOST'],dirname($_SERVER['PHP_SELF'])); // Cookie setzen; Name: key; Wert: $key; Verfallsdatum: zwei Stunden nach dem Setzen; Pfad und Domain werden durch PHP ermittelt
      4. // ggf. weitere Cookies setzen
      5. // Mail senden
      6. mail($_POST['email'], "Betreff", 'Klicke <a href="http://www.seite.de/optin.php?key=' . $key . '">hier</a>');
      7. ?>

      optin.php

      PHP-Quellcode

      1. <?php
      2. if ($_COOKIE['key'] == $_GET['key']) {
      3. do_something();
      4. }
      5. ?>

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von Malachite ()

    • Malachite schrieb:

      @MAP94: Ich habe dein Skript angeschaut: es hat zahlreiche Sicherheitslücken. Ein Glück, dass es eh nicht funktioniert (Handle vergessen etc.).
      Beispiel:

      PHP-Quellcode

      1. mysql_query("SELECT * FROM `optin` WHERE `key` = '" . $_GET["key"] . "'");

      Vom User eingegebene Daten ohne Prüfung in der DB nachschlagen?? Das lernt man eigentlich am Anfang, dass man das NIEMALS tun sollte! Wenn zum Beispiel $_GET['key'] so aussähe:

      Quellcode

      1. blubb';DROP TABLE 'optin

      dann sähe die Query so aus:

      SQL-Abfrage

      1. SELECT * FROM `optin` WHERE `key` = 'blubb';DROP TABLE 'optin'




      Hab das an der Stelle übersehen. Was hast du sonst noch für lücken gefunden?
    • OK, zahlreich ist vielleicht etwas übertrieben. Eine habe ich bisher gefunden, aber ich hab auch nicht explizit gesucht. Ich dachte nur, wenn es so lausig programmiert ist (Verwendung der alten MySQL- statt der neuen MySQLi-Schnittstelle, prozedurale (mit Handles) statt objektorientierte Datenbankabfragen, Real Escape String statt Prepared Statements), könnten noch mehr Lücken drin sein, also habe ich vorsorglich "zahlreich" geschrieben ;)

      Hier ist eine rundum erneuerte Version mit MySQLi, OOP und Prepared Statements. Außerdem habe ich noch eine Mailüberprüfung eingebaut:

      PHP-Quellcode

      1. <?php
      2. $mail = $_REQUEST['email']; // $_REQUEST enthält Cookie-, GET-, POST- und andere Daten, siehe PHP Manual
      3. if (filter_var($mail,FILTER_VALIDATE_EMAIL)) {
      4. die('Ung&uuml;ltige Adresse: '.$mail); // Adresse wird validiert; wenn sie (syntaktisch) ungültig ist, bricht das Skript mit dieser Meldung ab
      5. }
      6. $key = md5((string)mt_rand(1000000000,9999999999));
      7. $db = new MySQLi('localhost','root','gehtdichnixan','database'); // neues MySQLi-Objekt
      8. $stmt = $db->prepare('INSERT INTO optin (user,key) VALUES (?,?)'); // uid ist ein autoincrement-Wert, nehme ich mal an, daher muss er nicht in der Query erscheinen
      9. $stmt->bind_param('ss',$_REQUEST['user'],$key); // Hier können wir die Eingaben ungefiltert eingeben, da bei Prepared Statements die Query von den Daten getrennt wird, siehe http://de.wikipedia.org/wiki/Prepared_Statement
      10. $stmt->execute();
      11. $stmt->close();
      12. $db->close();
      13. mail($mail,$subject,'Cliquez ici: '.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'key='.$key);
      14. ?>
      Alles anzeigen

      PHP-Quellcode

      1. $db = new MySQLi('localhost','root','gehtdichnixan','database');
      2. $stmt = $db->prepare('SELECT * FROM optin WHERE key = ?');
      3. $stmt->bind_param('s',$_REQUEST['key']);
      4. $stmt->execute();
      5. $stmt->bind_result($uid,$user,$key);
      6. if ($stmt->num_rows == 0) {
      7. echo 'Freischaltungsschlüssel ungültig!';
      8. } else {
      9. unlock_user_or_do_other_things();
      10. }
      11. $stmt->close()
      12. $db->close()
      Alles anzeigen


      @Teelevision: Na und? Was hat er davon? Klar kann er seine Cookies manipulieren, aber das bringt nichts. Oder habe ich da was übersehen?
      Andernfalls kann man natürlich auch mit Sessions arbeiten, dann wird der Key halt auf dem Server gespeichert.

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von Malachite ()

    • Malachite schrieb:

      OK, zahlreich ist vielleicht etwas übertrieben. Eine habe ich bisher gefunden, aber ich hab auch nicht explizit gesucht. Ich dachte nur, wenn es so lausig programmiert ist (Verwendung der alten MySQL- statt der neuen MySQLi-Schnittstelle, prozedurale (mit Handles) statt objektorientierte Datenbankabfragen, Real Escape String statt Prepared Statements), könnten noch mehr Lücken drin sein, also habe ich vorsorglich "zahlreich" geschrieben ;)

      Hier ist eine rundum erneuerte Version mit MySQLi, OOP und Real Escape Strings Außerdem habe ich noch eine Mailüberprüfung eingebaut:

      PHP-Quellcode

      1. <?php
      2. $mail = $_REQUEST['email']; // $_REQUEST enthält Cookie-, GET-, POST- und andere Daten, siehe PHP Manual
      3. if (filter_var($mail,FILTER_VALIDATE_EMAIL)) {
      4. die('Ung&uuml;ltige Adresse: '.$mail); // Adresse wird validiert; wenn sie (syntaktisch) ungültig ist, bricht das Skript mit dieser Meldung ab
      5. }
      6. $key = md5((string)mt_rand(1000000000,9999999999));
      7. $db = new MySQLi('localhost','root','gehtdichnixan','database'); // neues MySQLi-Objekt
      8. $stmt = $db->prepare('INSERT INTO optin (user,key) VALUES (?,?)'); // uid ist ein autoincrement-Wert, nehme ich mal an, daher muss er nicht in der Query erscheinen
      9. $stmt->bind_param('ss',$_REQUEST['user'],$key); // Hier können wir die Eingaben ungefiltert eingeben, da bei Prepared Statements die Query von den Daten getrennt wird, siehe http://de.wikipedia.org/wiki/Prepared_Statement
      10. $stmt->execute();
      11. $stmt->close();
      12. $db->close();
      13. mail($mail,$subject,'Cliquez ici: '.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'key='.$key);
      14. ?>
      Alles anzeigen


      Yo so sieht mein script auch aus :D Also so von der Struktur her nur dass ich bis jetzt eben mit db einträgen gearbeitet hab und jetzt ist es halt so wie hier vorgeschlagen ;D
    • Malachite schrieb:

      @Teelevision: Na und? Was hat er davon? Klar kann er seine Cookies manipulieren, aber das bringt nichts. Oder habe ich da was übersehen?
      Der User kann sich einen eigenen Key erzeugen und diesen an die Webseite übergeben ohne die E-Mail empfangen haben zu müssen, bzw. er kann auch direkt den Key aus dem Cookie nehmen.
      Dass es nicht funktioniert, zeigt ja alleine schon diese Stelle: $_COOKIE['key'] == $_GET['key']
      Beides sind unsichere Daten, die vom User beliebig gesendet werden können.

      Das ganze ohne Datenbank zu lösen ist wahrscheinlich nicht wirklich machbar. Und da der User ja sowieso in einer Datenbank steht, hat man ja eine zur Verfügung.

      Man könnte auch einen Key aus Daten erzeugen, die sowieso vorhanden sind (Anmeldezeitpunkt, ...). Allerdings kann man diese auch erraten.
    • Teelevision schrieb:

      Malachite schrieb:

      @Teelevision: Na und? Was hat er davon? Klar kann er seine Cookies manipulieren, aber das bringt nichts. Oder habe ich da was übersehen?
      Der User kann sich einen eigenen Key erzeugen und diesen an die Webseite übergeben ohne die E-Mail empfangen haben zu müssen, bzw. er kann auch direkt den Key aus dem Cookie nehmen.
      Dass es nicht funktioniert, zeigt ja alleine schon diese Stelle: $_COOKIE['key'] == $_GET['key']
      Beides sind unsichere Daten, die vom User beliebig gesendet werden können.

      Das ganze ohne Datenbank zu lösen ist wahrscheinlich nicht wirklich machbar. Und da der User ja sowieso in einer Datenbank steht, hat man ja eine zur Verfügung.

      Man könnte auch einen Key aus Daten erzeugen, die sowieso vorhanden sind (Anmeldezeitpunkt, ...). Allerdings kann man diese auch erraten.

      Aber nur sehr unwahrscheinlich, dass jemand dazu in der Lage ist, solange der Ersteller der Seite nicht preisgibt, welche informationen verwendet werden.