Gibt es Techniken, um doppelte Einreichung in zustandslosen Web-Anwendungen zu verhindern?

8

Ich möchte doppelte Submission Prevention in einer bestehenden Java Web Application implementieren (struts tatsächlich). Architektonisch sprechen wir von 2 bis N möglichen Anwendungsservern (tomcat) und einem einzigen Datenbankserver (mysql). Die einzelnen Server kennen sich nicht und können keine Nachrichten austauschen. Vor den Anwendungsservern gibt es einen einzelnen Load Balancer, der sticky sessions ausführen kann.

Grundsätzlich gibt es also zwei Arten von Double-Submission-Prevention-Client-Seite und Server-Seite. Wenn möglich, möchte ich auf die Serverseite gehen, da alle clientseitigen Techniken scheitern, wenn die Leute Cookies und / oder Javascript in ihren Browsern deaktivieren.

Das bringt mich auf die Idee, eine Art Mutex-ähnliche Synchronisation über Datenbanksperren durchzuführen. Ich denke, es ist möglich, eine Prüfsumme der vom Benutzer eingegebenen Daten zu berechnen und sie in einer dedizierten Datenbanktabelle zu speichern. Bei jedem Antrag muss der Antrag auf Vorhandensein einer gleichen Prüfsumme prüfen, die anzeigen würde, dass die gegebene Einreichung ein Duplikat ist. Natürlich müssen die Prüfsummen in dieser Tabelle regelmäßig gelöscht werden. Das Problem ist der ganze Prozess der Überprüfung, ob es bereits eine doppelte Prüfsumme in der Datenbank gibt und das Einfügen der Prüfsumme, wenn es keine gibt, ist ein kritischer Abschnitt . Daher muss die Checksum-Tabelle vorher gesperrt und nach dem Abschnitt wieder entsperrt werden.

Mein Deadlock und Flaschenhals Alarmglocken beginnen zu klingeln, wenn ich über Tischschlösser nachdenke. Meine Frage ist also: Gibt es bessere Möglichkeiten, doppelte Übergaben in staatenlosen Webanwendungen zu verhindern?

Bitte beachten Sie, dass die Struts TokenInterceptor hier nicht angewendet werden können, weil sie es sind scheitert kläglich, wenn Cookies deaktiviert werden (es beruht auf der HTTP-Sitzung, die ohne Sitzungscookies einfach nicht vorhanden ist).

    
aeisele 19.09.2011, 16:08
quelle

3 Antworten

6

Eine einfachere DB-basierte Lösung wäre ungefähr so. Dies kann auch für mehrere Formulare generisch gemacht werden.

  • Verfügen über eine Datenbanktabelle, die zum Speichern von Tokens verwendet werden kann.
  • Wenn ein neues Formular angezeigt wird, fügen Sie eine neue Zeile in die Token-Tabelle ein und fügen Sie das Token als verstecktes Feld in das Formular ein.
  • Wenn Sie eine Formularübermittlung erhalten, wählen Sie für die Aktualisierung in der Zeile aus entspricht dem Token, das Sie als Teil des Formulars erhalten haben.
  • Wenn die Zeile immer noch existiert, dann ist dies das erste Senden. Verarbeiten Sie die Übergeben und löschen Sie die Zeile.
  • Wenn die Zeile nicht existiert, wurde das Formular bereits bearbeitet - Sie können einen Fehler zurückgeben.
gkamal 19.09.2011, 16:27
quelle
1

Die klassische Technik zur Vermeidung von doppelten Eingaben besteht darin, zwei IDs (beide als "verstecktes" Feld im HTML-Formular-Tag) zuzuweisen - eine "Sitzungs-ID", die von der Anmeldung bis zur Abmeldung gleich bleibt ...

Die zweite ID ändert sich mit jeder Eingabe ... serverseitig müssen Sie nur die "aktuell gültige ID" (sitzungsspezifisch) nachverfolgen ... wenn Sie eine "erneute Eingabe" erhalten (per Klick) happy-user oder ein "Refresh-Button" oder ein "Zurück-Button" oder ...) dann würde das nicht mit der aktuellen ID übereinstimmen ... auf diese Weise wisst ihr: Diese Submission sollte verworfen werden und eine neue ID generiert werden und schickte mit der Antwort zurück. Einige Implementierungen verwenden eine ID, die bei jeder Einreichung inkorporiert wird, was den Check / Kepp-Track-Teil etwas vereinfacht, aber anfällig für "Raten" ist (Sicherheitsbedenken) ... Ich möchte kryptografisch starke IDs für diese Art von Schutz erstellen ...

Wenn Sie eine Load-Balanced-Umgebung mit sticky-Sitzung haben, dann müssen Sie nur die ID auf dem Server selbst (in-memory) verfolgen ... aber Sie können sicherlich die ID in der DB speichern ... da Sie speichern es zusammen mit der Sitzungs-ID, die Sperre wäre auf "Zeilenebene" (nicht auf Tabellenebene), was in Ordnung sein sollte.

Die von Ihnen beschriebene Vorgehensweise geht noch einen Schritt weiter, indem Sie den Inhalt untersuchen ... ABER ich sehe den Inhalt mehr auf der "Anwendungslogik" -Ebene als auf der "Wiedervorlage-Verhinderungsstufe", da es von der App-Logik abhängt es will die gleichen Daten wieder aufnehmen ...

    
Yahia 19.09.2011 16:21
quelle
0

Was ist, wenn Sie mit sticky sessions arbeiten, dann wären Sie mit TokenManagement in Ordnung. Es gibt eine DoubleClickFilter , die du deinem web.xml hinzufügen kannst.

Da Sie Sticky-Sitzungen haben, brauchen Sie keine Cross-Tomcat-Lösung.

    
Fabian Barney 19.09.2011 16:27
quelle