HTML Formular doppelt senden verhindern und Cookie Frage

Domi83

Rear Admiral
Registriert
Feb. 2010
Beiträge
5.202
Hallo Leute, ich habe da mal eine kleine Frage an Euch und vielleicht kann mir der eine oder andere mal einen Denkansatz geben, denn ich stehe gerade ein wenig auf dem Schlauch.

Ich habe in HTML in Verbindung mit PHP ein Formular (eine Buchungsmaske), nun passiert es schon mal das am ende des Formulars (letzte Seite) schon mal ein Kunde / Besucher doppelt oder dreifach auf "submit" drückt und somit eine Doppelbuchung durchführt.

Wie verhindere ich denn eine Doppelbuchung am einfachsten..?
Es darf ja ruhig zwei mal gebucht werden, falls sich ein Wert ändert.. aber 100% gleiche Buchungen sind doof. Ich könnte jetzt alles umbauen und mit einer Checksumme prüfen lassen ob es die gleichen Daten sind und dann das Speichern in der Datenbank verhindern. Aber kann man es jetzt pauschal anders lösen?

Eine andere Frage ist folgende.. Das Formular hat mehrere Seiten. Und diese werden nicht nur durch einen Parameter generiert, sondern es sind wirklich physikalische Seiten (form1.php, form2.php, form3.php, form4.php) und die Daten werden mittels POST in eine SESSION gespeichert damit man Problemlos von Seite 1 auf 2 und zurück springen kann. Um eine Session zu verwenden, wird regulär ein PHPSSID Cookie im Browser angelegt.. DA folgt nun das Problem, wenn ich mein Formular via iFrame in einer meiner anderen Domains einbaue, und der Besucher Cookies von Drittanbieter-Seiten blockt, kann das PHPSSID Cookie nicht angelegt werden.

Hat jemand dafür einen Tipp für mich, wie man DAS am elegantesten lösen kann..?
Gruß, Domi
 
Deaktiviere den Submit-Button beim Anklicken.
 
schreib in das cookies, dass du gesendet hast oder so. der möglichkeiten gibt es viele.
 
@wahli, am einfachsten mit einem JavaScript.. Richtig? Oder gibt es da einen Befehl für dein INPUT den ich übersehen habe..?!

@evilbaschdi, joa.. Möglichkeiten gibt es bestimmt hunderte, aber ich saß hier und habe die ganze Zeit überlegt "was mache ich jetzt und was geht einfach?", dann kam mir die Idee mit der Checksumme.. aber dann müsste ich ja alles umbauen und das sollte erst zum Sommer geschehen, da ich hier noch einige andere Dinge auf dem Tisch liegen habe :D
 
1) Ich nehme mal an, das beim submit die Seite neu geladen wird und nicht mit Ajax gearbeitet wird. Hier kannst du ein hidden <input> einbauen, der einen zufallsstring enthält, quasi als Formular-Sitzungs-Schlüssel. Dieser wird wird immer dann geändert und protokolliert wenn die Daten verarbeitet werden. Auf dem Server prüfst du dann ob der "Formular-Schlüssel" schon mal verwendet wurde, der gerade übergeben wurde.
Das ganze kann man zusätzlich auch mit Javascript prüfen um unnötige Seitenaufrufe und damit Traffic zu vermeiden. Submit Ereignis abfangen, dem Formular in irgendeiner Weise ein Tag "bereits gesendet" verpassen und dann einfach if(!bereits_gesendet) submit(); Eine sichere Lösung ist JS allein aber nicht.

2) Hier würde mir nur einfallen, die Daten in der Sitzung auf Server Seite zu speichern, statt alles in das Cookie zu ballern. Bei allen Seitenaufrufen muss die Session ID in der URL übergeben werden, bzw. ebenfalls im Formular als zusätzliches Feld verstecken. Nach dem session_start() dann einfach zusätzlich session_id($get_sessid) und die Sitzung ist wieder da.
 
Das was Spike in seinem ersten Vorschlag beschreibt, nennt sich ein CSRF-Token (Google wird einiges dazu liefern) und ist so mit die beste mögliche Lösung.
 
Das mit einem Token für die Sitzung finde ich ziemlich gut und schaue mal, ob das genau den Effekt bringt wie ich es mir wünsche. Und ja, AJAX ist nicht in der Seite drin. Da bin ich nicht so fit drin, darum habe ich alles klassisch mit PHP aufgebaut. Es werden auch benötigte Input Felder via PHP geprüft ob sie ausgefüllt sind. Ist das nicht der Fall, geht es auch nicht in das nächste Formular.

Das einzige was ich gebaut habe, ist ein JavaScript was mir auf der ersten Seite on-demand die Prämie für eine Versicherung ausspuckt ab einem Bestimmten Wert der Versichert werden soll. Danach verlässt mich dann auch mein Wissen über JavaScript wieder :D

Was den Cookie angeht, die Daten sind ja in $_SESSION gespeichert, aber damit der Browser die Session wieder findet ist in der php.ini vom Server eingetragen das SESSION IDs im Cookie gespeichert werden sollen. Also die Daten selbst sind nicht in einem Cookie, lediglich die Session ID ist im Cookie, aber da funktioniert es ja auch nicht, wenn Cookies von Drittanbieter-Seiten verboten sind und ein iFrame mit im Spiel ist. Hoffe ich konnte das jetzt passender erklären :D

Gruß, Domi
 
Du wirst für iframes einfach keine zufriedenstellende Lösung finden, schließlich sind iframes an sich schon keine Lösung.
 
Naja, andere Versicherer haben es ja auch irgendwie gelöst bekommen und die bieten keine Schnittstellen an wodurch man das alles lösen könnte. Also sollte das ja bei uns auch machbar sein, dass man buchen kann trotz iframe :)
 
Schreib das Formular in eine Seite/Datei und unterteile sie per JS in Tabs.
 
Hm.. Das mit JS und einer Datei, probiere ich mal aus. Was AJAX an sich angeht, da bin ich noch etwas unerfahren. Ich habe es zwar schon mal hin gedreht, dass ich eine Eingabe in einem Feld machen kann und wenn ich fertig bin, wird etwas aus einer SQL Datenbank via JS abgefragt. Ob das nun als AJAX interpretiert werden kann, weiß ich nicht. Aber soviel kann ich sagen :)

Ich habe dem SUBMIT am Ende meiner Test Datei mal ein onclick verpasst, dass den Button dann per JS deaktiviert. Mal schauen was jetzt auf der aktiven Seite passiert, dort habe ich das auch eingebaut :)

Was die Übergabe der Session ID angeht, habe ich mal in meiner Testdatei etwas gebaut was am Anfang so aussieht...
Code:
<?php
 ini_set('session.use_only_cookies', '0');
 if(!$_GET['sid']) {
  session_start();
  header('Location: index.php?sid='.session_id($get_sessid));
 }
 $sessid = $_GET['sid'];
 session_id($sessid);
 session_start();

 if($_POST) {
  $_SESSION['username'] = $_POST['username'];
  $_SESSION['password'] = $_POST['password'];
 }
?>
Und man glaubt es kaum.. es funktioniert. Hat zwar den Nachteil, dass man die ID aus der URL hijacken könnte, aber wenn man mit der Eingabe fertig ist, wird die Session zerstört.. somit dürfte das auch wieder etwas sensibilisierter sein.
 
Wenn XMLHttpRequest oder $.ajax() oder ähnliches drin vorkommt, ist es sehr wahrscheinlich Ajax ;)

Einfach beim Klick den submit-Button deaktivieren ist schon gut, aber nur die viertel Miete. Wenn der Nutzer in einem Eingabefeld ist, kann er immernoch über die Enter-Taste senden...und wenn JS deaktiviert ist, sind alle Probleme wie gehabt.

Ja, das ist unschön, immer extra Parameter durchzuschleifen, aber wie JS sind Cookies eben nicht verlässlich genug für solche Zwecke. Um die Sessions sicherer zu machen, empfiehlt es sich, die zusammen mit anderen Parametern auf dem Server zu merken.

Noch ein Hinweis, if($_POST) und if(!$_GET['sid']) löst eine Warnung aus wenn keine Parameter übergeben wurden, je nachdem welches Errorlevel eingestellt ist (in der PHP Standard-Konfiguration auf jeden Fall). Über solche Meldungen freuen sich böse Buben. Daher: if(isset($_POST['username']) && isset($_POST['password']))
 
Zurück
Oben