Mehrfaches Absenden eines Formulars verhindern
Hallo,
ich hab eine Lösung gesucht um ein mehrfaches Abschicken eines Formulas durch Aktualisieren des Browsers oder Backtaste zu verhindern.
Dies habe ich so gelöst und es funktioniert:
Jedoch habe ich gelsen man sollte die ID in eine Datenbank speichern und dazu noch die aktuelle Zeit mit speichern.
Jetzt zu meiner Frage ist dies notwendig oder reicht auch meine Version?
Sollte ich noch was zu meinem Code ergänzen?
Oder gibt es noch besser/sichere Lösungen?
Ich würde mich auf eine schnelle Antwort freuen
Gruß
Sapzero
ich hab eine Lösung gesucht um ein mehrfaches Abschicken eines Formulas durch Aktualisieren des Browsers oder Backtaste zu verhindern.
Dies habe ich so gelöst und es funktioniert:
Datenbank verbunden -->
Tabelle erstellt mit ID,Text,Datum -->
<form name="formular" action="#" method="post">
<textarea name="text" cols="50" rows="4"></textarea>
<input name="send" style="margin-left: 10px" type="submit" value="Send" />
<input name="hidden" type="hidden" value="<?= uniqid(""); ?>">
</form>
$text = $_POST['text'];
$hidden = $_POST['hidden'];
if(isset($_POST['send']))
{
if($_SESSION["hidden"] != $_POST["hidden"])
{
$_SESSION["hidden"] = $_POST["hidden"];
if(strlen($_POST['text']) > 0)
{
$news = "INSERT INTO tblTest VALUES ('','$text',now())";
mysql_query($news) OR DIE ("Fehler beim Einfügen in die Tabelle:<br/ >".mysql_error());
echo "Text erfolgreich eingefügt!!!<br><br>";
}
else
{
echo "Ihr Text ist zu kurz!!!<br><br>";
}
}
else
{
echo "Mehrfaches einfügen verhindert!!!<br>";
}
}
Jedoch habe ich gelsen man sollte die ID in eine Datenbank speichern und dazu noch die aktuelle Zeit mit speichern.
Jetzt zu meiner Frage ist dies notwendig oder reicht auch meine Version?
Sollte ich noch was zu meinem Code ergänzen?
Oder gibt es noch besser/sichere Lösungen?
Ich würde mich auf eine schnelle Antwort freuen
Gruß
Sapzero
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 117214
Url: https://administrator.de/contentid/117214
Ausgedruckt am: 23.11.2024 um 01:11 Uhr
4 Kommentare
Neuester Kommentar
Was möchtest du denn nun verhindern?
Dass dein Formular mehrfach abgesendet wird, oder dass es mehrere identische Datensätze gibt?
Das sind zwei verschiedene Paar Schuhe.
Ich gehe mal aus, dass es bei deiner Lösung mit der uniqid() noch mehr Code gibt, als du uns hier zeigst - dann wäre das als CSRF-Schutz und gegen mehrfaches Absenden durchaus ausreichend (Zusätzlich sollte man dem Benutzer aber auch visuell zeigen, dass sein Formular abgesendet wurde).
Gegen Datenbankduplikate helfen aber nur Gegenprüfungen und UNIQUE-Constraints...
Und dann gibt es in deinem Code noch eine klassische SQL-Injection-Lücke...
Grüße
Max
Dass dein Formular mehrfach abgesendet wird, oder dass es mehrere identische Datensätze gibt?
Das sind zwei verschiedene Paar Schuhe.
Ich gehe mal aus, dass es bei deiner Lösung mit der uniqid() noch mehr Code gibt, als du uns hier zeigst - dann wäre das als CSRF-Schutz und gegen mehrfaches Absenden durchaus ausreichend (Zusätzlich sollte man dem Benutzer aber auch visuell zeigen, dass sein Formular abgesendet wurde).
Gegen Datenbankduplikate helfen aber nur Gegenprüfungen und UNIQUE-Constraints...
Und dann gibt es in deinem Code noch eine klassische SQL-Injection-Lücke...
Grüße
Max
Also ich wollte eigentlich nur verhindern das es nicht mehrere identische Datensätze gibt.
Dann musst du dein Datenbank-Schema entsprechend anpassen und evtl. noch einmal mit PHP kontrollieren, dass keine Duplikate entstehen.
Wo ist der Unterschied und wieso verhindert man mehrfaches Absenden eines Formulars?
Das hast du doch schon selbst geschrieben:
durch Aktualisieren des Browsers oder Backtaste zu verhindern.
Abgesehen davon gibt es auch durchaus noch sicherheitsrelevante Gründe. Siehe dazu: CSRF
Und könntest du mir noch sagen wo die SQL-Injection-Lücke ist?
Hier:
$news = "INSERT INTO tblTest VALUES ('','$text',now())";
Das war auch der ganze Code
Das passt so aber nicht.
Der Ablauf mit uniqid() muss folgender sein:
- uniqid() erzeugen und in SESSION-Variable speichern
- erzeugte Variable in Formular einbauen
- Nach dem Absenden die alte uniqid auf Gültigkeit prüfen und danach gleich eine neue erzeugen
Hier ist mal beispielhaft eine kurze Implementation:
<?php
/** Allgemeine Funktionen zu uniqid()s
* ====================================
* create_new_key() -> erzeugt eine neue uniqid() und sichert die alte <bei jedem seitenaufruf>
* check_key() -> prüft die alte uniqid() <für abgesendete formulare>
* current_key() -> die aktuelle uniqid() <beim erzeugen von formularen>
*/
function create_new_key()
{
$_SESSION['_oldkey'] = @$_SESSION['_newkey'];
$_SESSION['_newkey'] = uniqid();
}
function check_key($key)
{
return ($key === @$_SESSION['_oldkey']);
}
function current_key()
{
return $_SESSION['_newkey'];
}
//Um $_SESSION zu benutzen muss es eine aktive Session geben
session_start();
//Die Funktion erzeugt erstmal die uniqids();
create_new_key();
//folgender Code wird nur ausgeführt, wenn das Formular abgesendet wurde
if (isset($_POST['frm_sent'])) {
//Den alten Key gegen den gesendeten (=der alte) prüfen
if(!check_key($_POST['frm_sent']))
die("Das Formular ist nicht mehr gültig!");
}
?>
<html><body>
<form action="#" method="post">
<p>
<input type="hidden" name="actionkey" value="<?php echo current_key() ?>" />
<input type="submit" value="Absenden" name="frm_sent" />
</p>
</form>
</body></html>
Grüße
Max
Hallo Max,
vielen Dank für Dein ausführliches Beispiel das sehr hilfreich für mich war.
Wenn ich nicht irre hat sich in Zeile 33 ein Fehler eingeschlichen.
Zeile 33 sollte lauten: if(!check_key($_POST['actionkey']))
An Stelle von Zeile 34 habe ich folgenden Code eingefügt, durch den
der Aufruf des aktuellen Formulares ohne Übergabeparameter wie POST oder GET erfolgt:
header("Location: ".$_SERVER[PHP_SELF]);
In meinem Fall war dies sinnvoll da es sich um eine Tabelle mit Eingabemöglichkeiten handelte.
So wurde die Tabelle einfach erneut angezeigt ohne dass ungewollte Änderungen stattfanden.
Gruß
Reinhold
(Besser spät als nie)
vielen Dank für Dein ausführliches Beispiel das sehr hilfreich für mich war.
Wenn ich nicht irre hat sich in Zeile 33 ein Fehler eingeschlichen.
Zeile 33 sollte lauten: if(!check_key($_POST['actionkey']))
An Stelle von Zeile 34 habe ich folgenden Code eingefügt, durch den
der Aufruf des aktuellen Formulares ohne Übergabeparameter wie POST oder GET erfolgt:
header("Location: ".$_SERVER[PHP_SELF]);
In meinem Fall war dies sinnvoll da es sich um eine Tabelle mit Eingabemöglichkeiten handelte.
So wurde die Tabelle einfach erneut angezeigt ohne dass ungewollte Änderungen stattfanden.
Gruß
Reinhold
(Besser spät als nie)