Datensatz kann in mySQL nicht abgespeichert werden

  • Hallo!


    Ich bekomme bei Eingabe eines Datensatzes in meinem Formular ständig die Meldung, dass kein Datensatz eingefügt werden konnte. Ich habe schon sehr viel gesucht und nun habe ich mir gedacht, ich bitte das Forum mal um Unterstützung.


    Mein Code lautet wie folgt:


    Nach Eingabe erscheint folgende Meldung:


    pasted-from-clipboard.png


    Könnt ihr mir bitte mitteilen weswegen der Datensatz nicht gespeichert werden kann?


    Meine Datenbank in mySQL sieht wie folgt aus:


    pasted-from-clipboard.png

  • Wofür sind den die Punkte und " in deine query String ? Bist du sicher das es so sein muß ?

    Außerdem hast du Sql Sicherheitslücken in deinen Code.

    $_POST wird nicht ungefiltert in der Datenbank geschrieben.


    Dann nutzt du mal Hoch Kommers und mal wieder nicht.

    Es gibt auch noch die dünnen Hoch Kommers die man nutzen sollte.

    Zb so ( ungetestet )

    Code
    1. $sql = "INSERT INTO `login`(`Nachname`, `Vorname`, `Password`, `Username`, `EMail`, `Date`)
    2. VALUES('$na','$vn', '$pw', '$us', '$em', '$da')";

    escapen nicht vergessen.

    https://www.php.net/manual/de/mysqli.real-escape-string.php


    Ps : mysqli hat auch error ausgaben da stehen wichtige Hinweiße drinne wo du Fehler gemacht hast

    https://www.php.net/manual/de/mysqli.error.php

  • Nun habe ich die Passwortverschlüsselung integriert.


    Was mich jetzt beschäftigt ist, dass ich im Textfeld vom Formular nun das Datum und die Uhrzeit angezeigt bekommt, aber leider wird sie in der Datenbank nicht gespeichert. Ich möchte im Formular-Textfeld die aktuelle Uhrzeit mit dem aktuellen Datum angezeigt bekommen und dieses soll anschließend, nach betätigen des Buttons in der mySQL-Datenbank mit den weiteren Werten gespeichert werden.

  • input type="da" ?????

    type da gibt es nicht


    Code
    1. <p><input name="vn"> Vorname</p>
    2. <p><input name="na"> Nachname</p>
    3. <p><input name="us"> Benutzername</p>
    4. <p><input name="pw"> Passwort</p>
    5. <p><input name="em"> E-Mail-Adresse</p>

    ???????


    input type was ???


    Mach mal erst den den html Code richtig und dann geht es weiter zu SQL.

    Bezüglich der Filterung von $_POST würde mich interessieren, ob du die Verschlüsselung "Password_hash()" des Passwortes gemeint hast?

    Nee.Ich meine das


    Wenn html fertig ist kannst du dir hier mal drüber gedanken machen

    Code
    1. //Die Passwortverschlüsselung geschieht hier!
    2. $passwort = 'pw';
    3. $pw = password_hash($passwort, PASSWORD_DEFAULT);

    Wie kommt das pw den da hin ? Ein escaptes $_POST["pw"] hätte ich noch verstanden, aber so bringt das nix.


    Warum steht dein passwort_hash eigentlich am Ebde des Php Codes nochmal ?

  • Nun wird das Datum in der Datenbank abgespeichert und das Escape habe ich eingebaut. Ich hoffe, das Escape stimmt so?

  • Ich halte so Namen wie $na, $us, etc. für grausam. Bei längeren Scripten wirst du damit irgendwann den Überblick verlieren, deshalb solltest du besser $name, $user, etc. schreiben.

    Code
    1. //Die Passwortverschlüsselung geschieht hier!
    2. $passwort = 'pw';
    3. $pw = password_hash($passwort, PASSWORD_DEFAULT);

    Damit speicherst du immer das gehashte Passwort pw in die Datenbank


    Wieso fragst du in dem Formular das Datum ab? Einfach das aktuelle Datum selber ermitteln, bzw. beim insert ein now() verwenden

  • Wofür sind den die Punkte und " in deine query String ? Bist du sicher das es so sein muß ?

    Das ist normale PHP string-Verkettung.

    $_POST wird nicht ungefiltert in der Datenbank geschrieben.

    escapen nicht vergessen.

    NEIN., Falsch. (EDIT: ich hab hier übertrieben reagiert. Sorry.)


    romae Vergiss mysqli_real_escape_string. Die Funtion solltest Du nie wieder nutzen. (EDIT: ich hab hier übertrieben reagiert. Sorry.)

    Die Daten werden so wie sie sind in die db geschrieben.

    Außer Passwörter. (Loginpasswort richtig hashen - password_hash() & password_verify())

    Du musst aber alle Daten als nicht vertrauenswürdig ansehen.

    Bei der Ausgabe im (zB) Browser nutzt Du htmlspecialchars() order htmlentities().


    Welche Daten sind nicht verstrauenswürdig?

    Alle!

    Inputeingaben via POST order GET,

    Dateien (csv, txt, json, ... ALLE),

    Eingaben aus der console,

    Daten bezogen von einer API,

    ...,

    und selbst die Daten, die Du in Deiner db stehen hast.


    Zur db: Wer sagt, dass die sicher sind? Hat da nie nie niemals jemand was geändert? 100% sicher? NEIN.


    Also: alle Daten sind böse.

    Und deswegen macht es erst gar keinen Sinn da was beim Speichern in der db zu "escapen" ect.

    ABER: nutze Prepared Statements (PDO oder mysqli. Ich empfehle PDO).

    https://www.php.net/manual/de/pdo.prepared-statements.php

    https://www.php.net/manual/de/…t.prepared-statements.php


    Ich halte so Namen wie $na, $us, etc. für grausam.

    Yap. Sowas geht gar nicht.

    Dieser Beitrag wurde bereits 2 Mal editiert, zuletzt von cottton () aus folgendem Grund: Übertriebene Reaktion :/

  • Die Daten werden so wie sie sind in die db geschrieben.

    Nein, auf keinen Fall! Du wirst spätestens dann ein Problem bekommen, wenn ein User sowas eingibt:

    Code
    1. Mike's eMail

    Durch das einfache Hochkomma zerdrischt du das insert, weil du dann ungefähr sowas in String stehen hast

    Code
    1. insert into tabelle set abc='Mike's eMail'

    Das scheppert dann. Und SQL-Injektions sind sonst auch möglich.

  • Nein, auf keinen Fall! Du wirst spätestens dann ein Problem bekommen, wenn ein User sowas eingibt:

    Code
    1. Mike's eMail

    Durch das einfache Hochkomma zerdrischt du das insert, weil du dann ungefähr sowas in String stehen hast

    Code
    1. insert into tabelle set abc='Mike's eMail'

    Das scheppert dann. Und SQL-Injektions sind sonst auch möglich.

    Du hast es evtl nicht verstanden.

    Es sollte so aussehen:

    insert into tabelle set abc = :placeholder;


    Die Parameter für Prepared Statements müssen nicht maskiert werden. Der Treiber übernimmt das automatisch. Wenn eine Anwendung ausschließlich Prepared Statements benutzt, kann sich der Entwickler sicher sein, dass keine SQL-Injection auftreten wird. (Wenn aber trotzdem andere Teile der Abfrage aus nicht zuverlässigen Eingaben generiert werden, ist dies immer noch möglich.)

    Versuch doch mal eine SQL-Injection mit Platzhaltern.


    ---

    Wenn jetzt hier mysql values escapen und vars in die Query schreiben (fast schon) empfohlen wird,

    dann werd ich mich wohl verabschieden.

    Seit Jahren versuch ich den "neuen" mitzugeben, damit es irgendwann mal allgemein bekannt sein wird.

    Jetzt gehts auf einmal vollgas rückwärts - als wäre ich heute aufgestanden, und es ist 5 Jahre zurück :D

  • Mir wurde seid 2 Jahren gesagt das man gerade bei INSERT und UPDATE escapen soll.

    Habe ich irgendwo mal ein Beitrag geschrieben wo ich das nicht gemacht habe gab es gleich mecker.

    Ich bin ja auch noch am lernen, doch wenn man immer gesagt kriegt das man escapen soll und jetzt von einen höhrt ( der meiner meinung nach ahnung hat ) das man das nie wieder nutzen soll, verwirrt mich das auch.


    Wenn man in der Forum suche ( hier und andere Foren ) mysqli_real_escape_string eingibt sieht man das es schon fast jeder so gesagt hat wie ich im Post #2.


    Was ist den nun richtig ?

    Wenn man PreparedStatements verwendet brauch man kein  mysqli_real_escape_string 

    Wenn man ohne PreparedStatements arbeitet ist mysqli_real_escape_string  absolute Plicht ?

  • Wenn man PreparedStatements verwendet brauch man kein mysqli_real_escape_string

    Richtig, man braucht es nicht zwingend, i.d.R. könnte das sogar kontraproduktiv sein.

    Das gilt allerdings nur solange, wie Du als Entwickler den Aufbau Deiner Queries 100% unter Kontrolle hast. Arbeitest Du mit dynamisch generierten Queries, kann es durchaus sinnvoll und besser sein, eine escape_string Funktion einzusetzen.


    Wenn man ohne PreparedStatements arbeitet ist mysqli_real_escape_string absolute Plicht ?

    Auf jeden Fall empfehlenswert, ja.


    Es wird häufig behauptet, beide Funktionen machen das selbe, das ist aber nur die halbe Wahrheit.

    In der Kurzfassung kann man sagen: Eine escape_string Funktion versucht den kompletten String zu maskieren ( in den meisten Fällen also die komplette Query ), während sich die Prepared Statements "nur" um die Werte kümmern.

    Daher ist es einfach falsch zu sagen: nutz es am besten nie wieder!

    Wie man sieht und Du ja ehrlicher Weise zugegeben hast, verwirrt das die Leute, die dann denken, diese escape_string Funktionen seien veraltet o.ä.

  • "mysql prepared statements vs mysqli_real_escape_string"

    Zitat

    Should I use mysqli_real_escape_string or should I use prepared statements?

    Prepared statements only. Because nowhere escaping is the same thing. In fact, escaping has absolutely nothing to do with whatever injections, and shouldn't be used for protection.

    While prepared statements offer the 100% security when applicable.


    Also zu Deiner Frage: das erste ist richtig

    Wenn man PreparedStatements verwendet brauch man kein mysqli_real_escape_string

  • Sorry, aber das ist viel Quatsch.

    Zu viel, um es hier richtig zu stellen.

    Alleine Das hier:

    Eine escape_string Funktion versucht den kompletten String zu maskieren ( in den meisten Fällen also die komplette Query ),

    Ist schwammig und einfach falsch.


    Siehe einfach meinen Post vorher.

    Oder such im Netz. Stack ist schon eine ganz gute Quelle, da dort sehr viele sofort reagieren würden, wenn jemand Mist erzählt.

  • Dein Auszug aus SO ist willkürlich gewählt, es gibt haufenweise anderer Meinungen.

    Die die Du Dir gezogen hast ist warum die richtige?!


    Mal als Gegenbeispiel: https://stackoverflow.com/ques…mysqli-real-escape-string

    Antwort 1 ( als Antwort akzeptiert! ) sagt genau das, was ich geschrieben habe.

    Warum soll das also Quatsch sein, wenn Deins aus gleicher Quelle richtig sein soll?!


    Sorry, aber das ist viel Quatsch.

    Zu viel, um es hier richtig zu stellen.

    ...oder weil Du es nicht begründen kannst vielleicht?

    Bisher hast Du jedenfalls Deine Meinung noch nicht begründet, sondern nur gesagt, dass andere es nicht verstanden haben oder Quatsch schreiben.

  • Naja, ist doch richtig, was er da sagt.

    basically mysqli_real_escape_string will take out the junk in the user input according to a defined character set while prepared statements will make sure if there be any junk in the user input it will be only interpreted as you want it to be interpreted which is usually as user junk :)

    Grob gesagt: mysqli_real_escape_string den "Müll" zu entfernen (maskieren).

    Prepared statements ist der "Müll" egal, da eh nichts passieren kann, da (by default) als string in das Template eingefügt.


    Ich sehe da jetzt kein Gegenargument oder irgandwas, da meine Aussage jetzt als falsch dastehen lässt.

  • Irgendwie fehlt mir hier die Betrachtungsweise wie Prepared-Statements funktionieren und das man die Wahl der Methodik abhängig von der Anforderung bauen sollte. Prepared Statements sind zu bevorzugen soweit ich überhaupt etwas Preparen kann und dabei sollte man auch prüfen, was das Prepared-Statement noch so macht bzw. welche Einschränkungen dahinter liegen.


    Baue ich eine Middelware oder habe ein Setup bei dem ich nicht von vorne herein den aufbau der DB und oder den kommenden Input kenne, kann ich nicht mehr mit Prepared Statements arbeiten. d.h. immer wenn ich Dynamische Queries habe. Das gleiche gilt für Statements die außerhalb der CRUD Funktionalitäten liegen. Muss ich über Eingaben (egal ob vom User oder Konfigurationsdateien) die Datenbank modifizieren kann ich hier wieder keine Prepared Statements nutzen. Und hier gibt es auch für normale abfragen genügend beispiele bei denen PreparedStatements an ihre grenzen stoßen was die Parameter angeht oder mir fehlt irgendwo das wissen, wie ich z.B. vom User sowohl die abzufragenden Felder + dynamische wehre Bedingungen in ein Prepaid Statement setze. Oder ab einem bestimmten punkt bei dynamischen Queries dann doch der overhead von PreparedStatements zu Verschwendung von Ressourcen führt.


    Hier bleibt eines der Werkzeuge zur Validierung der eingaben weiterhin z.B. das Escapen über *_real_escape_string.


    Und ebenfalls verschleiert es für Anfänger die eigentliche Problematik: die Wichtigkeit der Validierung der eingaben. Man kann zwar statisch behaupten, "Nutze Prepared-Statements und deine Probleme sind gelöst" aber das wäre doch etwas naiv. Und auch aussagen "Nutze nie wieder eine Funktion/Modul xyz (obwohl sie noch supportet und nicht deprecated ist) wirkt auf mich auch eher als wolle man sich nicht mit der sache beschäftigen.


    Ich beziehe mich hier auf die generelle Diskussion zu dem Thema OP sollte für die im Eingang genutzte frage am besten ein PreparedStatement nutzen.


    Grüße


    Timo