Reihenfolge von htmlspecialchars(), strip_tags() und trim()?

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Reihenfolge von htmlspecialchars(), strip_tags() und trim()?

    Hallo,

    ich will aus dem $_POST-Array diverse Dinge filtern/ersetzen und nutze aktuell diesen Code:

    PHP-Code:
    $_POST array_map('htmlspecialchars'array_map('strip_tags'array_map('trim'$_POST))); 
    Macht diese Reihenfolge so Sinn?

    Können nicht ev. durch strip_tags() erneut links oder rechts vom String Leerzeichen entstehen?

    Danke!

  • #2
    strip_tags macht so gut wie nie Sinn.

    Und wie hilfreich oder nicht die anderen zwei sind, hängt davon ab, was du eigentlich erreichen willst.
    I don't believe in rebirth. Actually, I never did in my whole lives.

    Kommentar


    • #3
      Ich würde die Funktionen dort verwenden, wo sie erforderlich sind.

      htmlspecialchars() gehört in die HTML-Ausgabe und hat bei der POST-Verarbeitung nichts verloren.

      strip_tags() macht nur dann Sinn, wenn du gezielt HTML-Code herausfiltern möchtest, was in 99,9% der Fälle unnötig ist und nur die Daten verstümmelt.

      trim() brauchst du dann, wenn du Whitespaces am Anfang und Ende von Strings entfernen möchtest. Das kann bei Eingaben in Textfeldern sinnvoll sein.

      Kommentar


      • #4
        Ich will ein typisches Kontaktformular "filtern".

        Name, Straße, Ort, PLZ, eMail-Adresse...

        Da könnte ich jetzt natürlich überall Regexes benutzen, aber z.B. bei der Straße gibt's ja sonstwas für Namen mit Bindestrich, Apostroph, c/o usw.

        Deswegen soll eigentlich nur HTML raus sowie Leerzeichen...

        Kommentar


        • #5
          Zitat von h3ll Beitrag anzeigen
          strip_tags() macht nur dann Sinn, wenn du gezielt HTML-Code herausfiltern möchtest, was in 99,9% der Fälle unnötig ist und nur die Daten verstümmelt.
          Wie macht man es dann, wenn z.B. der Name in der Datenbank gespeichert wird (incl. HTML und Javascripts) und dann irgendwann mal bei der Generierung einer HTML-Rechnung wieder abgerufen wird?

          Ziel soll ja sein, dass der Name gleich von Anfang an "sauber" in der Datenbank landet.

          Kommentar


          • #6
            Zitat von Truncate Beitrag anzeigen
            Ich will ein typisches Kontaktformular "filtern".

            Name, Straße, Ort, PLZ, eMail-Adresse...

            Da könnte ich jetzt natürlich überall Regexes benutzen, aber z.B. bei der Straße gibt's ja sonstwas für Namen mit Bindestrich, Apostroph, c/o usw.

            Deswegen soll eigentlich nur HTML raus sowie Leerzeichen...
            Prinzipiell sollte $_POST nicht manipuliert werden. Betrachte $_POST als read-only. Filtere dort, wo es erforderlich ist. In dem Fall wohl bei der Formularverarbeitung.

            Adressen mit strip_tags() zu filtern ist so wie Spaghetti mit Strumpfhosen abzugießen. Es tut irgendwie das, was man will, aber es ist nicht der richtige Weg. Wenn du filtern möchtest, dann solltest du vernünftige Filterregeln aufstellen. Dafür muss man sich eben mit den Daten beschäftigen und sich informieren, was sinnvoll ist uns was nicht.

            Zitat von Truncate Beitrag anzeigen
            Wie macht man es dann, wenn z.B. der Name in der Datenbank gespeichert wird (incl. HTML und Javascripts) und dann irgendwann mal bei der Generierung einer HTML-Rechnung wieder abgerufen wird?
            Man beachtet den Kontextwechsel, was man immer tun sollte. Vertraue nie darauf, dass die Daten "sauber" sind!

            In dem Fall verwendet man bei der HTML-Ausgabe (und nur dort!) htmlspecialchars(). In der Datenbank hat das nichts verloren. Dort gehören nur Rohdaten rein.

            Kommentar


            • #7
              „Sauber“ hängt halt vom Ausgabekontext (HTML, CSV, PDF, …) ab. Die DB weiß aber in aller Regel nicht, was der Ausgabekontext ist. Oder: Es ergibt in aller Regel keinen Sinn, die Daten für einen bestimmten Ausgabekontext aufbereitet in der DB zu speichern, weil du damit einerseits die Daten verstümmelst (du kannst dann per SQL etwa nicht mehr nach „C&A“ suchen, sondern musst nach „C&A“ suchen, was inhaltlich wenig Sinn ergibt, weil die Firma nun mal „C&A“ heißt).

              Zudem verbaust du dir durch derlei ausgabeformatspezifische Veränderungen auch die Chance, die Daten problemlos in einem anderen Ausgabekontext zu nutzen (wenn du etwa aus den Daten eine CSV-Datei oder ein PDF generieren möchtest – beide Formate kennen kein & als "&"-Zeichen, du müsstest dann umständlich erst mal rückkonvertieren).

              Deshalb ist es fast immer geschickter, die Originaldaten unverändert abzuspeichern und erst während der Generierung der Ausgabe an den entsprechenden Ausgabekontext anzupassen.

              E: Das waren längst nicht alle Argumente, das so zu machen.



              Was ich in Sachen strip_tags immer ganz anschaulich finde: Du könntest einen Artikel schreiben mit dem Titel „Erklärungen zum <a>-Element“ oder eine Firma könnte den Namen „<meta> Webdesign“ haben oder so was in der Art. Das wäre eher blöd, wenn du darauf strip_tags anwendest, das dir dann die „vermeintlichen“ Tags raushaut, obwohl die normaler Inhalt sind.

              Spaghetti mit Strumpfhosen abzugießen
              Schönes Bild.
              Zuletzt geändert von mermshaus; 14.08.2015, 00:36.

              Kommentar


              • #8
                Gut ich konkretisiere mal den Fall, würde echt gerne wissen wie Ihr das handhaben würdet...

                Irgendwelche HTML-Codes sind nirgendwo nötig/optional, im Kontaktformular werden abgefragt:

                - Name
                - Adresse (Straße und Hausnummer)
                - PLZ
                - Ort
                - E-Mail-Adresse

                Alle Felder sind Pflichtfelder, bekommen also das Input-Attribut required.

                Desweiteren wird pattern="[0-9]{4,5}" und maxlength="5" für die PLZ festgelegt, damit sind sämtliche PLZen aus DE/AT/CH abgedeckt.

                Für die E-Mail-Adresse wird einfach type="email" festgelegt.

                Sofern der Benutzer also einen HTML5-fähigen Browser besitzt, ist das Abschicken eines leeren Formulars nicht mehr möglich und PLZ sowie E-Mail-Adresse werden clientseitig schon mal vorab auf das richtige Format kontrolliert.

                Ich hätte jetzt den Feldern Name, Adresse und Ort noch sowas wie pattern="[0-9A-zÀ-Üß-ü- ]+" verpasst, allerdings müßten da ja auch noch einige Sonderzeichen mehr rein wenn z.B. jemand "K&M" oder "Müller+Meier GmbH" schreibt etc.

                Das wird wohl aber nichts werden, da diese Regex ev. zu "hart" ist und die Anfrage ja 100%ig ankommen soll

                Was passiert nach dem Absenden? Die Felder werden mittels !empty() geprüft ob alle ausgefüllt, zusätzlich nochmals das Format von PLZ sowie E-Mail-Adresse.

                Danach erfolgt eine Ausgabe im Browser ala "Vielen Dank ".$_POST['Name']." für Deine Anfrage!" und es wird eine HTML-E-Mail an $_POST['email'] mit den eingegebenen Daten geschickt.

                Da die Ausgabe beide Male in HTML erfolgt, könnte ich doch diese 3er-Kombi benutzen oder?

                Kommentar


                • #9
                  Zitat von Truncate Beitrag anzeigen
                  Gut ich konkretisiere mal den Fall, würde echt gerne wissen wie Ihr das hDanach erfolgt eine Ausgabe im Browser ala "Vielen Dank ".$_POST['Name']." für Deine Anfrage!" und es wird eine HTML-E-Mail an $_POST['email'] mit den eingegebenen Daten geschickt.

                  Da die Ausgabe beide Male in HTML erfolgt, könnte ich doch diese 3er-Kombi benutzen oder?
                  Kontextwechsel beachten!

                  PHP-Code:
                  Vielen Dank <?php echo htmlspecialchars($_POST['Name'], ENT_QUOTES ENT_HTML5'UTF-8'); ?> für Deine Anfrage!

                  Kommentar


                  • #10
                    Irgendwelche HTML-Codes sind nirgendwo nötig/optional
                    Kam vermutlich schon in den Erklärungen durch, aber das ist eigentlich irrelevant, wenn man die Kontextwechsel alle passend beachtet. Dann kann in den Daten stehen, was will.

                    Sofern der Benutzer also einen HTML5-fähigen Browser besitzt, ist das Abschicken eines leeren Formulars nicht mehr möglich und PLZ sowie E-Mail-Adresse werden clientseitig schon mal vorab auf das richtige Format kontrolliert.
                    Ich sage es nur zur Sicherheit: Du musst natürlich dennoch alle Daten auch noch serverseitig prüfen, da HTTP-Requests von Nutzern (auch ohne Browser) beliebig aufgebaut und an den Server geschickt werden können.

                    Ich hätte jetzt den Feldern Name, Adresse und Ort noch sowas wie pattern="[0-9A-zÀ-Üß-ü- ]+" verpasst, allerdings müßten da ja auch noch einige Sonderzeichen mehr rein wenn z.B. jemand "K&M" oder "Müller+Meier GmbH" schreibt etc.
                    Dazu vertrete ich den Standpunkt: Wer Unsinn eintragen will, der schafft das so oder so. „Mordor Weltbeherrschung KGaA“ ist zum Beispiel nicht grundsätzlich weniger quatschig als irgendein Zeichensalat wie „×÷±∞π∅≤≥≠≈∧∨“. Quark bleibt halt Quark, auch wenn der eine Quark noch lesbarer ist. Würde mir deshalb gut überlegen, welche Gründe es gibt, die möglichen Zeichen wie zu reduzieren. (Das soll nicht suggerieren, dass derlei Gründe nicht existieren.)

                    Das wird wohl aber nichts werden, da diese Regex ev. zu "hart" ist und die Anfrage ja 100%ig ankommen soll
                    Joa, genau. So was ist gar nicht so leicht. Ich weiß da auch keine Patentlösung. „Alles erlauben“ ist aber erst mal besser als „nur ~100 Zeichen, die ich gerade passend fand, erlauben“, denke ich.

                    zusätzlich nochmals das Format von PLZ sowie E-Mail-Adresse.
                    Ah, gut. Damit wird der eine Hinweis oben mehr oder weniger hinfällig.

                    Da die Ausgabe beide Male in HTML erfolgt, könnte ich doch diese 3er-Kombi benutzen oder?
                    Nutz einfach beim Eintrag in die DB die Escaping-Funktion für den Kontextwechsel nach SQL und bei Ausgabe (und nicht vorher) als HTML die Escaping-Funktion für den Kontextwechsel nach HTML. Das ist Schema F, und das ist völlig üblich so.

                    Kontextwechsel nach SQL: Je nach Adapter zum Beispiel: mysqli_real_escape_string, PDO::quote, Prepared Statements, …
                    Kontextwechsel nach HTML: siehe hellbringer

                    Da es glaube ich noch niemand verlinkt hat: Schöne Artikel zum allgemeinen Thema Kontextwechsel:

                    - PHP/Anwendung und Praxis/Kontextwechsel ? SELFHTML-Wiki
                    - PHP/Anwendung und Praxis/Kontextwechsel/erkennen und behandeln ? SELFHTML-Wiki

                    Kommentar

                    Lädt...
                    X