Michael: Doppelte Aktionen erkennen/verhindern

Hallo,

ich will doppelte Aktionen, die z.B. durch einen Reload einer Seite ausgelöst werden, erkennen können. Dabei werden mittels GET und/oder POST Daten übertragen und entsprechende Aktionen ausgeführt. Die einzige Möglichkeit scheint mir jeder Seite eine eindeutige ID mitzugeben und diese dann abzufragen. Mit Cookies habe ich es schon versucht, aber das kann nicht funktionieren, da mir keine zuverlässige Methode eingefallen ist, die Cookies richtig zu setzen (das Problem ist, dass auch beim reload einer Seite ein neues Cookie übertragen wird und der Seite somit eine neue ID zugeordnet wird - und dann erscheint die Aktion als wäre sie "neu"). Eine Methode die sicher funktionieren würde, wäre einfach an die Links, bzw. Action-Attribute der Formulare eine eindeutige ID anzuhängen. Das wäre aber für meinen Fall ziemlich umständlich, weil mein Projekt schon recht gross geworden ist und überall diese IDs anzuhängen wäre deshalb nicht die beste Lösung.

Gibt es eine weitere Möglichkeit einer Seite eine eindeutige ID mit auf den Weg zu geben, die dann z.B. im HTML Code selbst gespeichert wird und immer dann übermittelt wird, wenn ein Link angeklickt wurde oder ein Formular übermittelt wird (wobei ich Formulare auch separat lösen könnte)? Ich dachte da an sowas wie versteckte Formularfelder (aber wie übertrage ich die beim anklicken "normaler" Links?). Bietet mir der Webserver (in meinem Fall Apache 2.0.52) eine Möglichkeit Reloads zu erkennen (Ich habe z.B. die Variable UNIQUE_ID des Apachen gesehen, aber ich glaube nicht, dass die's tut).

btw: ich benutze PHP 5.0.2 mit Apache 2.0.52 auf Linux.

Gruss,
   Michael

  1. Hallo Michael.

    ich will doppelte Aktionen, die z.B. durch einen Reload einer Seite ausgelöst werden, erkennen können.

    Was spricht gegen Sessions? Ich habe es so gelöst, dass ich eine Sessionvariable "sent" im Erfolgsfall auf "true" gesetzt habe. Vor dem Absenden des Formulares wird sie über $_SESSION['sent'] abgefragt, falls true: Fehlermeldung, ansonsten weiter im Text.

    Freundschaft!
    Siechfred

    --
    Hinweis an alle Karnevalsmuffel: Aschermittwoch ist alles vorbei.
    1. Hallo Siechfred,

      danke für die Antwort - nur so ganz verstanden habe ich es noch nicht.

      Wenn eine Seite aufgerufen wird, dann speicherst du in _SESSION["sent"] = true. Wird sie wieder aufgerufen, dann schaust du, ob _SESSION["sent"] == true, wenn ja dann setzt du es auf false, ansonsten ist ein Fehler aufgetreten? Habe ich das so richtig verstanden?

      Was ist, wenn der Benutzer aber eine andere Aktion auf der selben Seite ausführen will? Wie unterscheidest du das von einem Reload? _SESSION["sent"] wäre immernoch false, aber es wäre eigentlich eine gültige Aktion?

      Bei mir gibt es ein Script edit.php, das via GET eine Variable action übergeben bekommt. Das sind ungefähr 10 unterschiedliche Aktionen. Das Skript erzeugt die Seite und bearbeitet auch die Aktionen, d.h. alle Links auf edit.php zeigen wieder auf edit.php, aber u.U. mit einer unterschiedlichen action Variable.

      Gruss,
          Michael

      Hallo Michael.

      ich will doppelte Aktionen, die z.B. durch einen Reload einer Seite ausgelöst werden, erkennen können.

      Was spricht gegen Sessions? Ich habe es so gelöst, dass ich eine Sessionvariable "sent" im Erfolgsfall auf "true" gesetzt habe. Vor dem Absenden des Formulares wird sie über $_SESSION['sent'] abgefragt, falls true: Fehlermeldung, ansonsten weiter im Text.

      Freundschaft!
      Siechfred

      1. Hallo Michael.

        Wenn eine Seite aufgerufen wird, dann speicherst du in _SESSION["sent"] = true.

        Nein, erst beim Absenden. Zuerst wird geprüft, ob bereits eine Session besteht. Falls ja, wird geprüft, ob "sent" wahr ist, in diesem Fall kommt die Fehlermeldung.

        Was ist, wenn der Benutzer aber eine andere Aktion auf der selben Seite ausführen will? Wie unterscheidest du das von einem Reload? _SESSION["sent"] wäre immernoch false, aber es wäre eigentlich eine gültige Aktion?

        Die Sessionvariable muss nur eindeutig zuordenbar sein, also z.B.:

        $_SESSION['fb_sent'] -> wurde ein Feedback abgegeben?
        $_SESSION['gb_sent'] -> wurde ein Gästebucheintrag hinterlassen?

        usw.

        Btw, bitte kein TOFU :)

        Freundschaft!
        Siechfred

        --
        Hinweis an alle Karnevalsmuffel: Aschermittwoch ist alles vorbei.
        1. Hallo du da draußen,

          Wenn eine Seite aufgerufen wird, dann speicherst du in _SESSION["sent"] = true.
          Nein, erst beim Absenden. Zuerst wird geprüft, ob bereits eine Session besteht. Falls ja, wird geprüft, ob "sent" wahr ist, in diesem Fall kommt die Fehlermeldung.

          Was ist, wenn der Benutzer wirklich zwei verschiedene Gästebucheinträge oder Ähnliches hinterlassen will?

          Bei mir habe ich es (unsauber aber einfach) gelöst, indem ich das Ergebnis von mtime() als Parameter übermitteln lasse, und das zusammen mit der IP-Adresse in einer Datei speichere. Ohne Sessions. Aber dazu müsste man ja wieder hidden-Felder eintragen, was Michael afaik nicht wollte.

          Grüße von hier drinnen, aus Biberach an der Riss,
          Candid Dauth (Dogfish)

          --
          »Bismarck biss Mark, bis Mark Bismarck biss!«
          http://cdauth.net.tc/
          ie:{ fl:( br: va:} ls:[ fo:| rl:( n4:( ss:) de:> js:( ch:| sh:( mo:) zu:|
        2. Hallo,

          wie gewünscht diesmal kein TOFU (und wikipedia sei Dank, weiß ich auch was TOFU ist :-)).

          Die Sessionvariable muss nur eindeutig zuordenbar sein, also z.B.:

          $_SESSION['fb_sent'] -> wurde ein Feedback abgegeben?
          $_SESSION['gb_sent'] -> wurde ein Gästebucheintrag hinterlassen?

          Ich versteh's immer noch nicht. Der Benutzer kann ja auch die selbe Aktion mit unterschiedlichen Daten gleich hintereinander ausführen (ich glaube das ist das was Candid Dauth auch meinte). Da bliebe als eindeutige Sessionvariable nur eine ID, wie sie z.B. uniqid() erzeugt. Die müsste ich dann aber auch auf der Seite, die ich an den Browser sende speichern und da wäre ich dann wieder beim alten Problem. Wie speichere ich sie dort so, dass sie bei einem Reload nicht wieder neu gesetzt wird (was bei Cookies der Fall wäre). Sie müssten also irgendwo im HTML Code gespeichert werden. Vielleicht stehe ich auch noch immer mit beiden Beinen auf meinem Schlauch :-/

          Nach meinem Verständnis muss jeder Anfrage an den Server eine eindeutige ID zugeordnet werden. Anfragen, die durch ein Reload ausgelöst werden, müssen aber die gleiche ID senden. Ein Mehrfaches anklicken eines Links ist aus Sicht des Servers wohl nichts anderes als ein Reload. Es bleibt mir also wohl nichts anders übrig als jedem Link eine ID anzuhängen und in der Ergebnisseite wieder eine andere ID an die Links (bzw. Formular Action Attribute) anzuhängen. Damit würde beim ausversehenen doppelten anklicken von Links (und den damit u.U. doppelten Anfragen) und beim neu laden einer Seite die selbe ID übertragen werden. Andererseite könnte der Benutzer auf der Ergebnisseite wieder eine Aktion ausführen, die dann eine neue ID hätte und somit wieder als gültig erkannt werden könnte.

          Danke & Gruss,
             Michael

          1. Hallo Michael.

            Ich versteh's immer noch nicht. Der Benutzer kann ja auch die selbe Aktion mit unterschiedlichen Daten gleich hintereinander ausführen (ich glaube das ist das was Candid Dauth auch meinte).

            Du kannst in einer Session alles speichern, die Daten müssen halt so eindeutig sein, dass nur das (versehentliche) Mehrfachabsenden eines Formulares verhindert wird.

            Wie speichere ich sie dort so, dass sie bei einem Reload nicht wieder neu gesetzt wird (was bei Cookies der Fall wäre). Sie müssten also irgendwo im HTML Code gespeichert werden.

            Was verstehst du unter Reload? Dass die Seite neu vom Server angefordert wird oder dass sie mittels Zurück-Button userseitig aus dem Cache geholt wird?

            Jedenfalls brauchst du irgendein Merkmal, das eindeutig ist. Nehmen wir z.B. ein Forum, die Beantwortung geschieht immer über das gleiche Formular. Wenn jedes Posting eine eindeutige ID hat, sollte es doch kein Problem sein, für diese ID eine Variable "sent" auf wahr zu setzen. Damit wäre genau eine Antwort möglich, das Antworten auf ein anderes Posting mittels des gleichen Formulares wäre danach trotzdem möglich. Das Ganze könntest du in einem versteckten Eingabefeld unterbringen. Mit PHP fragst du dann ab, ob für diese Session bereits eine Antwort mit der eindeutigen ID existiert und reagierst entsprechend darauf. Das Ganze könnte man ggf. noch mit einer Zeitsperre kombinieren.

            Freundschaft!
            Siechfred

            --
            Hinweis an alle Karnevalsmuffel: Aschermittwoch ist alles vorbei.
      2. Hallo, Michael!

        Hallo Siechfred,

        danke für die Antwort - nur so ganz verstanden habe ich es noch nicht.

        Wenn eine Seite aufgerufen wird, dann speicherst du in _SESSION["sent"] = true. Wird sie wieder aufgerufen, dann schaust du, ob _SESSION["sent"] == true, wenn ja dann setzt du es auf false, ansonsten ist ein Fehler aufgetreten? Habe ich das so richtig verstanden?

        nein. true wird erst beim absenden des formulares gesetzt. dadurch wird dieses formular mit dieser id als schon einmal abgesendet registriert und beim nochmaligen click auf den submit-knopf durch den user nicht mehr ausgewertet, sondern z.b. eine fehlermeldung zurückgegeben.

        Was ist, wenn der Benutzer aber eine andere Aktion auf der selben Seite ausführen will? Wie unterscheidest du das von einem Reload? _SESSION["sent"] wäre immernoch false, aber es wäre eigentlich eine gültige Aktion?

        wenn er das formular nicht absendet, wird ja in der auswertungsroutine send auch nicht true gesetzt.

        Bei mir gibt es ein Script edit.php, das via GET eine Variable action übergeben bekommt. Das sind ungefähr 10 unterschiedliche Aktionen. Das Skript erzeugt die Seite und bearbeitet auch die Aktionen, d.h. alle Links auf edit.php zeigen wieder auf edit.php, aber u.U. mit einer unterschiedlichen action Variable.

        und? wird edit.php ohne eine gültige id aufgerufen, wird es mit einer id ausgeliefert. für diese id wird beim absenden des ausgefüllten formulars send auf true gesetzt, so dass diese id sozusagen "ungültig" wird. sendet der user das formular noch mal ab, erhält er eine fehlermeldung, ruft er es über den normalen link auf der seite neu auf, erhält es wieder eine neue id mit send = false.

        freundl. Grüsse aus Berlin, Raik