Flufo: Problem mit Back-Button / Session / POST

Hallo Forum,

habe folgendes Problem:
Ich habe ein Script wo Daten per POST, GET und SESSION gemischt bzw. abwechseln übertragen werden.

Die Problematik: Unter bestimmten umständen zeigt mir der IE 6, wenn ich auf den Back-Button klicke, folgende Meldung an:
----------------------------------------------------
Achtung: Seite ist nicht mehr gültig Die angeforderte Seite wurde mit Hilfe von Informationen erstellt, die von Ihnen in einem Formular mitgeteilt wurden. Diese Seite ist nicht mehr verfügbar. Als Sicherheitsmaßnahme übermittelt Internet Explorer solche persönlichen Informationen nicht automatisch erneut.

Falls Sie die Seite ansehen und die Informationen erneut mitteilen möchten, klicken Sie auf Aktualisieren.
----------------------------------------------------

Das ist ja sicherheitstechnisch ganz nett und ja auch nicht der Weltuntergang da ich ja per 'Aktualisieren' trotzdem weiter komme. Nur ein wenig unschön ist es dann doch:

Meine Frage:
Unter welchen Voraussetzungen genau taucht diese Meldung überhaupt auch?
Wie sollte man programmieren das diese Meldung nicht erscheint?

Flufo

PS: Mir geht es weniger um mein konkretes Problem das ich gerade habe sondern eher allgemein. Deswegen gibts auch keinen Code (könnte den Code auch nicht wirklich erklären/rechtfertigen da er zum grössten Teil aus fremder Hand stammt).

  1. Halli,

    Meine Frage:
    Unter welchen Voraussetzungen genau taucht diese Meldung überhaupt auch?

    Wenn die im expires-http-header (oder im entspr. meta-Element) angegebene Zeit abgelaufen ist.
    Daraus ergibt sich auch, wie Du sie vermeiden kannst.

    cu,
    Robert

    1. Wenn die im expires-http-header (oder im entspr. meta-Element) angegebene Zeit abgelaufen ist.
      Daraus ergibt sich auch, wie Du sie vermeiden kannst.

      Brauchte ein bißchen um das nachzuvollziehen und hab da noch weiter geforscht.
      Hier nun eine kleine Ergänzung wie es sich realisieren lässt:

      Gefunden auf --> http://www.dclp-faq.de/q/q-http-caching.html

      $expire = 15; # Lebensdauer der Seite im Cache in Minuten
      $exp_gmt = gmdate("D, d M Y H:i:s", time() + $expire * 60) ." GMT";
      $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) ." GMT";

      HTTP 1.0

      header("Expires: " . $exp_gmt);
      header("Last-Modified: " . $mod_gmt);

      HTTP 1.1

      header("Cache-Control: public, max-age=" . $expire * 60);

      und scheint bei mir auch gut zu funzen

      flufo

  2. Moin Moin !

    Mein Standard-Workaround für solche Zickereien diverser Browser:

    Der POST-Request wird mit einer Seite beantwortet, die gleich per Javascript auf die nächste Seite weiterleitet. Sollte aber auch für Javascript-Hasser mit <meta http-equiv="Refresh" content="0; url=/path/to/nextpage.html"> funktionieren.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
    1. Der POST-Request wird mit einer Seite beantwortet, die gleich per Javascript auf die nächste Seite weiterleitet. Sollte aber auch für Javascript-Hasser mit <meta http-equiv="Refresh" content="0; url=/path/to/nextpage.html"> funktionieren.

      Dann schick doch lieber gleich die Antwort "Created" oder "Accepted" (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2). Damit kann wenigstens jeder etwas anfangen.

      Gruß,
        soenk.e

      1. Moin Moin !

        Dann schick doch lieber gleich die Antwort "Created" oder "Accepted" (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2). Damit kann wenigstens jeder etwas anfangen.

        Technisch richtig, aber für die DAUs, die mit meinem Programm arbeiten müssen, ist es einfach Hirn-kompatibler, auf eine "alles klar"- oder Menü-Seite umzuleiten.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. Dann schick doch lieber gleich die Antwort "Created" oder "Accepted" (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2). Damit kann wenigstens jeder etwas anfangen.

          Technisch richtig, aber für die DAUs, die mit meinem Programm arbeiten müssen, ist es einfach Hirn-kompatibler, auf eine "alles klar"- oder Menü-Seite umzuleiten.

          Oha, es ist einfacher, sich durch mehrere Zeilen HTML und Javascript zu wühlen, als die Verarbeitung mit zwei Zeilen à la

          header("HTTP/1.0 201 Created");             // Daten akzeptiert und..
            header("Location: http://bla.bla/ok.html"); // ..Weiterleitung.

          abzuschließen? Deine DAUs sollten sich dringend mal die Gehirnwindungen entwinden lassen ;)

          Gruß,
            soenk.e

      2. Hallo Sönke,

        Dann schick doch lieber gleich die Antwort "Created" oder "Accepted" (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2). Damit kann wenigstens jeder etwas anfangen.

        Ich persönlich würde lieber per 303 (falls HTTP/1.1 verwendet wird) oder 302 (falls HTTP/1.0 verwendet wird) umleiten. Denn genau für diesen Zweck wurde 303 gemacht: die Weiterleitung der Antwort einer POST-Anfrage auf eine cachebare Resource, die mit GET aufgerufen werden soll. Created heißt »Resource erstellt« und ist IMHO unsinn, wenn Du nicht gerade PUT verwendest, und Accepted heißt, dass der Server noch arbeitet, was ja auch nicht mehr der Fall ist.

        Grüße,

        Christian

        --
        Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
        1. Ich persönlich würde lieber per 303 (falls HTTP/1.1 verwendet wird) oder 302 (falls HTTP/1.0 verwendet wird) umleiten. Denn genau für diesen Zweck

          Oha, ganz so versiert bin ich leider, gerade mit dem HTTP-Header-Krams noch nicht.

          Hab auch schon unter
          http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2
          und
          http://www.php.net/manual/de/function.header.php
          mich versucht ein wenig klug zu lesen. Hat aber leider nicht viel gebracht.
          Könnt ihr das vielleicht noch mal kurz Praxisnäher erklären (Code). Und was ich damit genau bewirke.

          Wäre wirklich nett.

          Flo

          1. Hallo Flo,

            Oha, ganz so versiert bin ich leider, gerade mit dem HTTP-Header-Krams noch nicht.

            Was nicht ist, kann noch werden.

            mich versucht ein wenig klug zu lesen. Hat aber leider nicht viel gebracht.
            Könnt ihr das vielleicht noch mal kurz Praxisnäher erklären (Code). Und was ich damit genau bewirke.

            Mit der PHP-Funktion Header schickst Du einen HTTP-Header mit. Dieser kann entweder der Statuscode sein, oder ein zusätzliches Feld.

            Zuerst musst Du einen Statuscode senden. Dies machst Du, indem Du nach HTTP/ die verwendete Version von HTTP (entweder 1.0 oder 1.1) sendest, danach ein Leerzeichen, danach der Statuscode und danach ein kurzer englischer Text.

            Der Statuscode

            HTTP/1.1 303 See Other

            bewirkt zum Beispiel, dass der Browser weiß, dass er auf eine andere Seite umleiten muss, auf der dann das Ergebnis der Anfrage steht. Dieses Ergebnis darf der Browser dann auch cachen. Die verwendete HTTP-Version (einschließlich HTTP/) bekommst Du über $_SERVER['SERVER_PROTOCOL']. Bei dieser Lösung musst Du noch sehen, ob HTTP/1.0 verwendet wird, wenn das der Fall ist, dann solltest Du "302 Found" senden, (genaugenommen macht das PHP automatisch, wenn Du keinen eigenen Statuscode sendest und eine Weiterleitung (s.u.) machst) denn HTTP/1.0 kennt kein "303 See Other". ("302 Found" klappt auch bei HTTP/1.1, aber das war eigentlich für etwas anderes gedacht, und nur weil die Browser sich wie gewünscht verhalten, heißt das noch lange nicht, dass das so bleiben muss, deswegen solltest Du für HTTP/1.1 den »richtigen« Statuscode verwenden)

            Sönke hat statt dem 303-Status-Code vorgeschlagen, "201 Created" oder "202 Accepted" zu verwenden. Ich persönlich bin gegen diese Lösung, aber diese Lösungen dürften an sich auch funktionieren, vom Code her ist es etwa die gleiche. (Sowohl 201 als auch 202 gibte es auch in HTTP/1.0, daher brauchst Du keine Abfrage wie bei 302 oder 303) Der Code "201 Created" bedeutet, dass die geforderte Resource erstellt wurde. Der Code "202 Accepted" heißt, dass die Anfrage akzeptiert wurde, aber sie noch in Bearbeitung ist. Beide beinhalten eine Weiterleitung. IMHO sind diese Statuscodes aber unpassend, denn die Anfrage ist a) fertig und b) hast Du keine HTTP-Resource erstellt.

            Danach musst Du noch mitgeben, auf welche Seite er weiterleiten soll. Dazu solltest Du den Location-Header verwenden. Der Location-Header sieht so aus:

            Location: Zieladresse

            Wobei Zieladresse eine _absolute_ Adresse _einschließlich_ http://... sein muss. Also z.B. http://selfhtml.teamone.de/html/. Wenn ein entsprechender Statuscode, der eine Weiterleitung impliziert, mitgesendet wurde, dann leitet der Browser automatisch auf die neue Resource weiter. (Beziehungsweise sollte er es tun, und je nach Statuscode sollte er vorher den Benutzer fragen, die Benutzerabfrage macht aber bisher überhaupt keinen Browser - was genau wann zu tun ist, ist an den enspr. Stellen des RFC 2616 beschrieben)

            Zusammengefasst:

            Header ('...');

            schickt den HTTP-Header ... (das macht jetzt hier natürlich wenig Sinn)

            Als erstes musst Du einen passenden Statuscode verschicken. Danach musst Du den Location-Header verschicken, damit der Browser dann weiß, wohin. Bei der 303er-Lösung sähe das in Pseudocode so aus:

            if (/* wenn die HTTP-Version 1.1 verwendet wurde */) {
              /* sende den Header "HTTP/1.1 303 Found"  */
            }
            /* andernfalls sendet PHP automatisch den 302-Status-Code */

            /* hier jetzt den Location-Header versenden */

            Ich hoffe, ich konnte Dir weiterhelfen.

            Grüße,

            Christian

            P.S.: In der FAQ dieses Forums steht, wie man Links setzt, aber das nur nebenbei.

            --
            Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
            1. Erstmal ein dickes Danke für die ausführliche Hilfe!

              Eins hab ich aber noch nicht verstanden.
              Was ist mit der Seite auf die ich weiterleite?
              Muss ich die dann extra erstellen? <-- wäre ja irgendwie umständlich
              Erstellt die sich automatisch?
              Oder hab ich da was falsch verstanden und da muss überhaupt nix zusätzliches erstellet werden.
              <grübel>
              Oder ... halt, funktioniert es so das dem Browser quasi nur _vorgetäscht_ wird das es sich NICHT um eine POST-Seite sondern eine ganz normale handelt und er sie somit cached?
              Aber wenn es so ist ergeben sich dadurch dann nicht andere Probleme?

              cu - Flo alias Flufo

              P.S.: In der FAQ dieses Forums steht, wie man Links setzt, aber das nur nebenbei.

              <grins> das klappt dann doch schon so ;-)))

              1. Hallo Flo,

                Was ist mit der Seite auf die ich weiterleite?
                Muss ich die dann extra erstellen? <-- wäre ja irgendwie umständlich
                Erstellt die sich automatisch?
                Oder hab ich da was falsch verstanden und da muss überhaupt nix zusätzliches erstellet werden.

                Doch, Du musst die Bestätigungsseite selbst erzeugen. Dazu eignen sich Sessions. Du speicherst in der Session alle Infos, die Du brauchst, um die Antwort auszugeben, unter einer eindeutigen Nummer (also unter $_SESSION['answer_infos'][$id] wobei $id z.B. eine Zufallszahl ist) und dann leitest Du an http://host/answer.php?id=245681111 weiter. Diese Seite holt sich alle Infos, die sie zur Generierung der Antwortseite braucht. Dann gibt sie die Antwortseite aus. Du kannst Dich übrigens nicht darauf verlassen, das die Antwortseite nur einmal aufgerufen wird, Browser mit mangelhaften Cachingeinstellungen holen sie jedes mal vom Server. :-( Daher solltest Du die Infos, die Du zum Erstellen der Antwort brauchst, möglichst kompakt halten, damit die Session nicht unnötig groß wird. Wenn Du nur ein einziges Formular hättest und das sowieso immer die gleiche bestätigungsseite hat, dann wäre es natürlich einfacher, dann könntest Du auf eine statische HTML-Seite weiterleiten.

                Oder ... halt, funktioniert es so das dem Browser quasi nur _vorgetäscht_ wird das es sich NICHT um eine POST-Seite sondern eine ganz normale handelt und er sie somit cached?

                Nein.

                Ach ja, eine HTTP-Weiterleitung hat einen weiteren Vorteil: sie erzeugt keinen zusätzlichen History-Eintrag, d.h. wenn der Benutzer (nachdem er auf einen Link geklickt hatte) auf »Zurück« klickt, dann landet er auf der Antwortseite und wenn er es nochmal tut, dann landet er wieder beim Formular, jedoch nie beim Verarbeitungsscript. (es sei denn, er schickt das Formular noch mal ab, aber das solltest Du sowieso abfangen, es sei denn, das würde nichts ausmachen (es gibt ein paar Fälle, wo dem der Fall ist))

                Grüße,

                Christian

                --
                Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
                1. Wow klasse, jetzt schliesst sich der Kreis. Hat mir wirklich weitergeholfen. Danke!

                  cu Flufo

                2. hab doch noch was:
                  wie ist das dann mit der session
                  gibt es da irgendwelche auswirkungen drauf oder macht das für die session keine untschied ob die seite umgeleitet oder normal aufgerufen wird?

                  1. Hallo Flo,

                    gibt es da irgendwelche auswirkungen drauf oder macht das für die session keine untschied ob die seite umgeleitet oder normal aufgerufen wird?

                    Es macht keinen Unterschied. Und zwar deswegen nicht, da die Umleitung durch den Browser ausgeführt wird, der ganz normal mit GET die Seite aufruft. Das wäre dann so, als ob sie über einen Link aufgerufen würde.

                    Grüße,

                    Christian

                    --
                    Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
  3. Die Problematik: Unter bestimmten umständen zeigt mir der IE 6, wenn ich auf den Back-Button klicke, folgende Meldung an:

    Achtung: Seite ist nicht mehr gültig. Die angeforderte Seite wurde mit Hilfe von Informationen erstellt, die von Ihnen in einem Formular mitgeteilt wurden.

    Meine Frage:
    Unter welchen Voraussetzungen genau taucht diese Meldung überhaupt auch?

    Unter der Voraussetzung, die dort im zweiten Satz genannt wird: Die Seite ist das Ergebnis eines abgeschickten Formulars, wurde also anhand der erhaltenen Formulardaten erstellt.

    Um die Seite aufzufrischen, müsste sie nochmal abgerufen werden, was wiederum bedeutet, daß das Formular nochmals abgeschickt werden müsste, was schlußendlich dazu führt, daß das, was mit dem Formular bezweckt wurde, doppelt ausgeführt wird.

    Es kann sein, daß man die Browser (Mozilla macht's genauso) mit entsprechenden Expires- oder Cache-Control-Angaben dazu bewegen kann, sich die Seite länger zu merken. Zum Format siehe RFC zu HTTP/1.1: http://www.w3.org/Protocols/rfc2616/rfc2616.

    Gruß,
      soenk.e