PHP Code Generator und abgleich mit SQL auf Einmaligkeit

  • PHP

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Link.

    PHP Code Generator und abgleich mit SQL auf Einmaligkeit

    Neu

    Moin Zusammen,

    ich steh gerade mal wieder extrem auf dem Schlauch und benötige Schwarmwissen.
    Ich versuche einen x Stelligen Code zu generieren, ähnlich einem Passwortgenerator.
    Wenn der Code generiert ist, soll dieser in einer SQL Datenbank abgefragt werden, wenn er schon vorhanden ist, soll erneut generiert und geprüft werden.
    Ist der Code noch nicht in der Datenbank, soll er hinzugefügt werden.
    Mein Problem besteht jetzt nicht an der Abfrage oder dem Einfügen, eher an dem wie ich die Schleife zum Prüfen mache.

    Hier mal mein bisheriger Code:

    PHP-Quellcode

    1. <?PHP
    2. include("../inc/config.php");
    3. function gen_identifier ( $passwordlength = 8, $numNumberChars = 0, $useCapitalLetter = false )
    4. {
    5. $numberChars = '123456789';
    6. $secureChars = 'abcdefghijklmnpqrstuvwxyz';
    7. $stack = '';
    8. $stack = $secureChars;
    9. if ( $useCapitalLetter == true )
    10. $stack .= strtoupper ( $secureChars );
    11. $count = $passwordlength - $numNonAlpha - $numNumberChars;
    12. $temp = str_shuffle ( $stack );
    13. $stack = substr ( $temp , 0 , $count );
    14. if ( $numNumberChars > 0 ) {
    15. $temp = str_shuffle ( $numberChars );
    16. $stack .= substr ( $temp , 0 , $numNumberChars );
    17. }
    18. $stack = str_shuffle ( $stack );
    19. return $stack;
    20. }
    21. $vorhanden = true;
    22. while($vorhanden == true) {
    23. $ident = gen_identifier (1,0);
    24. $a_code = $pdo->query("SELECT ident FROM qsl_ident WHERE ident = '".$ident."'");
    25. if($a_code->RowCount() === 0)
    26. $vorhanden = false;
    27. $pdo->query("INSERT INTO qsl_ident (user, ident) VALUES ('1', '".$ident."')");
    28. }
    29. echo $ident;
    30. ?>


    Wo mache ich meinen Denkfehler?
    Danke und Grüße,
    Stefan
    Nein! Doch! OHH!

    Neu

    Uhm, schreibst du mit der aktuellen Schleife, nicht jedes mal den Wert in die Datenbank, egal ob gefunden oder nicht?
    Edit: Zeile 32 ist nicht teil der Bedingung von Zeile 30.

    Ohne es ausprobiert zu haben:

    PHP-Quellcode

    1. $ident = '';
    2. while (true) {
    3. $ident = gen_identifier(1, 0);
    4. $a_code = $pdo->query("SELECT ident FROM qsl_ident WHERE ident = '" . $ident . "'");
    5. if ($a_code->RowCount() === 0)
    6. {
    7. break;
    8. }
    9. }
    10. $pdo->query("INSERT INTO qsl_ident (user, ident) VALUES ('1', '" . $ident . "')");
    11. echo $ident;


    PS:
    Bau deine Queries nicht mit String-concatenation, benutze eher PDO prepared statements/Prepared Statements
    Siehe: SQL Injection

    Edit:
    Wobei ich das eventuell in eine eigene Funktion packen würde:

    PHP-Quellcode

    1. <?php
    2. function foobar() {
    3. while (true) {
    4. $ident = gen_identifier(1, 0);
    5. $a_code = ...; // check query
    6. if ($a_code->RowCount() === 0)
    7. {
    8. // insert query
    9. return $ident;
    10. }
    11. }
    12. }

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „slice“ ()

    Neu

    @slice
    danke für die schnelle Hilfe.
    Im fertigen Script wirds später mit Prepare gemacht, wobei hier kein Inject möglich wäre, da es nicht über den User ausgeführt wird.
    Soll nur ein Background worker werden. Aber sicher ist sicher ;) Die Prepare kommen auf jedenfall mit rein.
    Vielen Dank,
    Stefan
    Nein! Doch! OHH!

    Neu

    Achja, ich würde auch noch ein Limit einbauen, damit der While-Loop nicht unendlich läuft. Auch wenn es unwahrscheinlich ist, die Gefahr besteht trotzdem.

    Entweder mit ner zusätzlichen Variable oder direkt als for-Loop und dann eine Fehlermeldung zurückgeben.

    Neu

    @slice
    Ich hab den Generator jetzt auch auf 5 Sellen eingestellt, war vorher nur 1 zum testen.
    Habe eine andere Abfrage vorgeschalten, wenn bereits ein User mit der ID in der Tabelle steht, wird erst gar kein Code generiert sondern der in der Datenbank ausgegeben.
    Aber dank dir vielmals für das Brainstorming ;)
    Nein! Doch! OHH!

    Neu

    Servus,

    ich kenne nicht den Zweck deines Vorhabens, aber falls es drum geht, einen row identifier zu haben weil man keine numerischen auto-increment ids exposen will, könnte man auch über UUID() nachdenken, MySQL supported das (uuidv1 zwar, aber was soll's - sicherlich kann man sich new uuidv4 procedure zamwurschten, aber wer hat auf sowas schon Bock).

    Alternativ kannst du einen hash der auto-increment ID rausgeben, quasi zusammen gehashed mit einem random string der nur intern bekannt ist. Zum Beispiel sha1($row->id . 'rAnD0M$3cR3t'). Das kann später dann in SQL auch verwendet werden kann, um den Datensatz zu finden (Beispiel: SELECT * FROM `table` WHERE SHA2(CONCAT(`id`, 'rAnD0M$3cR3t'), 256) = '830a604d5561dd422cb75fa0f6ccd6838ab4b9ea2c028f94344ddaefc2cbf16f';, was Datensatz #123 finden würde).

    Mit beiden Varianten musst du dir um die uniqueness schonmal keine Gedanken machen, wobei die zweite Variante insofern "besser" ist als dass hierbei der random String nicht fortlaufend ist, man kann also unmöglich ermitteln, was der vorherige oder nächste Datensatz ist. Und man braucht keine extra Spalte dafür. Nachteil ist, dass es relativ wenig performant ist.

    Als dritte Option käme noch in Frage, dass man random strings in eine Spalte schreibt (was du ja eh machst), die aber so lang sind, dass man erst gar nicht prüfen muss, ob es ein Duplikat gibt. Quasi ne Spalte vom Typ Varbinary(64) und dann beim Insert aus PHP heraus dann random_bytes(64) mit geben.

    Falls das beschriebene für dich nicht hilfreich ist und mit deiner Thematik so überhaupt gar nix zu tun hat, kannst du diesen Post ignorieren, wofür es, wenn du bis hier gelesen hast, ohnehin zu spät ist xD


    Grüße
    Link 8-)
    Hello World

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Link“ ()