Andreas: doppelte Script-Ausführung durch refresh verhindern

Hallo!
Ich habe ein Script, welchem der Parameter 'produktID' per GET übergeben wird, in dem entsprechende productID in eine DB eingetragen wird. Problem ist, wenn das script ausgeführt wurde, aber jemand aus irgendeinm Grund auf 'refresh' drückt, wird dasselbe nochmals eingetragen. Das habe ich versucht zu verhindern, indem ich zuerst die bisherigen Einträge prüfe, ob diese ID bereits vorhanden ist. Aber das ist nicht das was ich will, da das evtl. anderen Funktionalitäten im Weg steht.
Ich will nur prüfen, ob es ein Refresh ist, oder nicht. Gibt es eine Möglichkeit zu prüfen, ob der aktuelle Request 100%ig mit dem letzten übereinstimmt, oder was anderes in der Art? Wie komme ich sicher(das es immer funktioniert, in in jedem Browser...) an den aktuellen, UND den vorherigen Request, um ein Refresh zu erkennen? Ich hatte überlegt immer vom aktuellen Request die MD5 Prüfsumme zu bilden, den mitzugeben, und im nächsten Script wieder Prüfsumme bilden und vergleichen. Was sagt Ihr dazu? Welche Variable(HTTP_REFERER?) nehme ich dafür am besten?

Viele Grüße
Andreas

  1. Hoi Andreas

    Gemäss http://www.dclp-faq.de/q-formular-mehrfach.html gibts da nichts. Und ich denke die sollten das doch wissen... ??

    kaepten

    1. Hi kaepten!

      Gemäss http://www.dclp-faq.de/q-formular-mehrfach.html gibts da nichts. Und ich denke die sollten das doch wissen... ??

      Das meine ich nicht, hat jetzt nichts mit Formularen zu tun, außerdem - warum soll es dafür nichts geben, wenn es da nicht steht?

      Bei mir geht es weniger um Formulare, mehr um Links wie seite.php?ID=123&action=insert

      genau das sorgt auf seite.php dafür, dass ID 123 in die DB geschrieben wird. Wenn Du jetzt in Deinem Browser - warum auch immer auf "Aktualisieren" drückst, wird dasselbe ein 2. mal eingetragen. Das könnte man ja dadurch verhindern, das man irgerndwie guckt, ob selbiger Request von selbigem Client direkt zuvor gesendet wurde.

      Da gibts ja z.B. REQUEST_URI, wo die entsprechenden Parameter alle stehen. Jetzt müßte man das in geeigneter Form bei Ausführen des Scripes speichern, und beim nächsten Ausführen mit der aktuellen Version vergleichen. Problem, man muß sicherstellen, das es derselbe Client ist, und das es direkt der nächste Aufruf ist. Mit Sessions müßte das eigentlich möglich sein, also in der Session jedesmal REQUEST_URI speichern, und jedesmal gucken, ob identisch, und dann alle inserts, deletes und updates stoppen.

      Ohne Sessions bräuchte ich wiohl eine DB, in der ich wenigstens IP und das ein oder andere Merkmal zur wiedererkennung speichere.

      Oder kennt da jemand eine bessere Möglichkeit?

      Aber was sollte ich jetzt in der Session speichern? den Inhalt in REQUEST_URI(funktioniert das auch IMMER?) direkt speichern, oder eine Prüfsumme darüber speichern? Welche Funktion würdet Ihr für eine Prüfsumme empfehlen?

      Vielle Grüße
      Andreas

      1. Hoi Andreas

        Das meine ich nicht, hat jetzt nichts mit Formularen zu tun, außerdem - warum soll es dafür nichts geben, wenn es da nicht steht?

        Weil ->

        Und ich denke die sollten das doch wissen... ??

        Bei mir geht es weniger um Formulare, mehr um Links wie seite.php?ID=123&action=insert

        genau das sorgt auf seite.php dafür, dass ID 123 in die DB geschrieben wird. Wenn Du jetzt in Deinem Browser - warum auch immer auf "Aktualisieren" drückst, wird dasselbe ein 2. mal eingetragen. Das könnte man ja dadurch verhindern, das man irgerndwie guckt, ob selbiger Request von selbigem Client direkt zuvor gesendet wurde.

        Wo liegt beim Refresh der unterschied zu mehrmaliges versenden eines Formulares?

        All Deine Vorschläge könnten ja möglicherweise auf die eine oder andere Art durchaus funktionieren. Aber der Aufwand scheint mir schon etwas gross und ohne Sessions oder halt Cookies wirds wohl sicher nicht gehen.

        Zur Indentifikation könntest Du die Session-ID verwenden, da brauchst Du nichts selbst zu erfinden!

        Machs doch sie wie Lactrik es vorgeschlagen hat. Es ist wohl die einzig zuverlässe Variante.

        kaepten

        1. Hallo!

          Wo liegt beim Refresh der unterschied zu mehrmaliges versenden eines Formulares?

          Formular meist per POST, normaler Link per GET. In SCRIPT_URI steht ja alles was ich brauche um zu erkennen, ob der Request genau derselbe ist wie zuvor, bei POST ist das schon etwas schwieriger, da weiß ich noch nicht geanu wie man das am besten macht, bzw. welche Enviroment-Variablen hierfür geeignet sind, Ideen?

          All Deine Vorschläge könnten ja möglicherweise auf die eine oder andere Art durchaus funktionieren. Aber der Aufwand scheint mir schon etwas gross und ohne Sessions oder halt Cookies wirds wohl sicher nicht gehen.

          Cookies ist doof da abschaltbar. Aber ich stimme zu, wenn kein Auth-User, dann bleibt wohl nur die Session, wobei auch mit anderen Merkmalen sollte das zu 99% sicher gehen, denn das gleichzeitig 2 Leute mit gleicher IP, gleicher Konfigutration... zum gleichen Zeitpunkt sich da gegenseitig behindern ist wohl eher nur theoretisch möglich.

          Zur Indentifikation könntest Du die Session-ID verwenden, da brauchst Du nichts selbst zu erfinden!

          Wird wohl so gemacht.

          Machs doch sie wie Lactrik es vorgeschlagen hat. Es ist wohl die einzig zuverlässe Variante.

          Siehe Antwort, das ist etwas komplizierter, das habe ich wie gesagt zur Zeit so. ich will mir aber eine Funktion schreiben, die auf alle Fälle Fehler durch drüchen von "aktualisieren" oder doppelt abgeschickte Formulare verindern, und nachdem ich mich jetzt ein bisschen damit beschäftigt habe, bin ich mir Sicher, das es 100%ig funktionieren wird, nur noch ein paar Feinheiten sind zu klären, zum einen welche Variablen bei POST-Reqest, und wie ich das in der Session speichere, als Püfsumme oder nicht, und wenn ja mit welcher Funktion.

          Viele Grüße
          Andreas

  2. Hallo!
    Ich habe ein Script, welchem der Parameter 'produktID' per GET übergeben wird, in dem entsprechende productID in eine DB eingetragen wird. Problem ist, wenn das script ausgeführt wurde, aber jemand aus irgendeinm Grund auf 'refresh' drückt, wird dasselbe nochmals eingetragen. Das habe ich versucht zu verhindern, indem ich zuerst die bisherigen Einträge prüfe, ob diese ID bereits vorhanden ist. Aber das ist nicht das was ich will, da das evtl. anderen Funktionalitäten im Weg steht.
    Ich will nur prüfen, ob es ein Refresh ist, oder nicht. Gibt es eine Möglichkeit zu prüfen, ob der aktuelle Request 100%ig mit dem letzten übereinstimmt, oder was anderes in der Art? Wie komme ich sicher(das es immer funktioniert, in in jedem Browser...) an den aktuellen, UND den vorherigen Request, um ein Refresh zu erkennen? Ich hatte überlegt immer vom aktuellen Request die MD5 Prüfsumme zu bilden, den mitzugeben, und im nächsten Script wieder Prüfsumme bilden und vergleichen. Was sagt Ihr dazu? Welche Variable(HTTP_REFERER?) nehme ich dafür am besten?

    Moin,

    hmm, ich würd einfach einbauen, dass der vorher in der Datenbank prüft, ob der Eintrag schon vorhanden ist... wenn ja => meldung. Wenn nein => Eintrag vornehmen.

    Grüsse
    Lactrik

    1. Hallo!

      hmm, ich würd einfach einbauen, dass der vorher in der Datenbank prüft, ob der Eintrag schon vorhanden ist... wenn ja => meldung. Wenn nein => Eintrag vornehmen.

      Zitat:

      [...]Das habe ich versucht zu verhindern, indem ich zuerst die bisherigen Einträge prüfe, ob diese ID bereits vorhanden ist. Aber das ist nicht das was ich will, da das evtl. anderen Funktionalitäten im Weg steht.
      Ich will nur prüfen, ob es ein Refresh ist, oder nicht.[...]

      Ich will nur ermitteln, ob es ein Refresh ist. Eine andere Funktion wäre z.B., das man später nochmal auf bestellen bei gleicher ID klickt, um noch eins zu bestellen, dann soll hier Anzahl erhöht werden, was ja nicht geht, da man sowas nicht von einem "versehentlichen" Refresh unterscheiden kann.

      Außerdem brauche ich diese Funktionalität auch an anderer Stelle, z.B. wenn ich ein Formular abschicke, wobei ich da das Problem sehe, das ich da beo POST nicht mehr über REQUEST_URI an den String komme. Kennt jemand für POST eine adäquaten Ersatz um zu erkennen, ob es nochmal genau derselbe Request ist?

      Grüße
      Andreas

      1. Hoi Andreas

        Ich will nur ermitteln, ob es ein Refresh ist. Eine andere Funktion wäre z.B., das man später nochmal auf bestellen bei gleicher ID klickt, um noch eins zu bestellen, dann soll hier Anzahl erhöht werden, was ja nicht geht, da man sowas nicht von einem "versehentlichen" Refresh unterscheiden kann.

        Vielleicht solltest Du Dich gar nicht darum kümmern, ob ein Besucher mit "Refresh" nochmals denselben Artikel in den Warenkorb fügt. Er kanns ja dann selbst sehen im Warenkorb und am Preis nach sieht er es ja auch... Es handelt sich hier ja nicht direkt um das verhindern eines Benutzerfehlers, der nicht mehr rückgängig gemacht werden könnte. -> du hast das Problem ja selbst erkannt: Wie solltest Du feststellen können ob es gewollt oder ungewollt ist. Den Refresh an und für sich kannst Du (IMO) _nicht_ feststellen

        Außerdem brauche ich diese Funktionalität auch an anderer Stelle, z.B. wenn ich ein Formular abschicke, wobei ich da das Problem sehe, das ich da beo POST nicht mehr über REQUEST_URI an den String komme. Kennt jemand für POST eine adäquaten Ersatz um zu erkennen, ob es nochmal genau derselbe Request ist?

        AHA :-) und plötzlich sind wir wieder beim Thema: "Wie verhindere ich mehrfaches Absenden eines Formulars?"

        Falls Du es nicht wissen solltest: Du hast auch andere Umgebungsvariablen wie nur REQUEST_URI. Versuchs z.B. mal mit: $HTTP_POST_VARS etc. ;-)

        HTH
        kaepten

        1. Hallo!

          Vielleicht solltest Du Dich gar nicht darum kümmern, ob ein Besucher mit "Refresh" nochmals denselben Artikel in den Warenkorb fügt. Er kanns ja dann selbst sehen im Warenkorb und am Preis nach sieht er es ja auch... Es handelt sich hier ja nicht direkt um das verhindern eines Benutzerfehlers, der nicht mehr rückgängig gemacht werden könnte. -> du hast das Problem ja selbst erkannt: Wie solltest Du feststellen können ob es gewollt oder ungewollt ist. Den Refresh an und für sich kannst Du (IMO) _nicht_ feststellen

          Wieso nicht? Man kann nur nicht unterscheiden, ob jemand auf einer Seite auf denselben Link klickt, wei auf der Seite davor, oder ob es sich um ein Refresh handelt. Da ich ersteres mal ausschließen möchte, sollte es eindeutig sein, oder?
          Und selbst das könnte man mit dem Referer herausbekommen, nur ist der ja leider nicht sicher, daher lase ich Ihn lieber außen vor - auch ohne ist mir das sicher genug.

          AHA :-) und plötzlich sind wir wieder beim Thema: "Wie verhindere ich mehrfaches Absenden eines Formulars?"

          Ja, aber da ist es nicht ganz so wichtig, da ich hier die besagte obere Funktion(gewünscht oder nicht) nicht brauche, daher kann ich hier überprüfen, ob die Werte gleich oder nicht.

          Falls Du es nicht wissen solltest: Du hast auch andere Umgebungsvariablen wie nur REQUEST_URI. Versuchs z.B. mal mit: $HTTP_POST_VARS etc. ;-)

          Das Leben kann so blöd sein - wie doof bin ich denn heute - klar ;-)))
          Das kombiniert mit $PHPSELF sollte recht eindeutig sein.

          Jetzt bleibt nur noch die Frage, wie ich die Daten speichere.
          Ich muß das ja später vergleichen, am besten kopiere ich sämtliche $_POST bzw. $_GET Variablen in einen Prüf-Array, und füge $SCRIPT_URI an den Array an, speicher den Array in der Session, und prüfe das auf der nächsten Seite, oder? Oder doch nur die Prüfsumme? Was meint Ihr?

          Zeit zu speichern bringt wohl NULL Verbeserung, oder?

          Viel Grüße
          Andreas

          1. Hallo!

            So habe ichs geamacht, so kompliziert ist es gar nicht:

            <?
            $last_request = $_SESSION["last_request"];
            $this_request = array($_POST,$_GET,$SCRIPT_URI);

            if ($this_request==$last_request){
               echo "REFRESH, schade!";
            }else {
               echo "NEUE Werte!!!";}

            $_SESSION["last_request"] = $this_request;
            ?>

            Das sollte wirklich sicher sein, oder? Bis jetzt funktioniert es super!

            Viele Grüße
            Andreas

  3. Hallo Andreas,

    ich habe das jetzt so verstanden, dass in jeder Session das Script nur einmal ausgeführt werden darf.

    Da gibts verschieden Möglichkeiten. Mitführen eines Counters für jedes Script und vergleichen, ob der für die Session schon mal da war.

    Setzen eines Cookies. Da ist meines Erachtens die einfachste Möglichkeit. Wenn das Script das zweite mal aufgerufen wird, ist das Cookie schon da und du kannst das im Script abfragen. Sollte aber eines mit kurzer Verfallsdauer sein, damit der Kunde in einer Stunde wieder kaufen kann...

    Eintrag einer ID in eine Liste für das Script. Die ID wird als hidden-Feld bei der Erstübertragung der Seite initialisiert und beim ersten Abspeichern abgelegt in einer Datei auf dem Server. Ist so ne Art Cookie für Arme.

    Liebe Grüße

    Tom