Ankündigung

Einklappen
Keine Ankündigung bisher.

Datensätze lieber mit Prepared Statements aus lesen? oder doch per query ?

Einklappen

Neue Werbung 2019

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

  • Datensätze lieber mit Prepared Statements aus lesen? oder doch per query ?

    Hey erstmla Hallöchen, bin neu hier im Board.

    Die Frage steht ja schon oben.

    Man kann per Prepared Statement ja auch genau so gut daten aus der datenbank auslesen (also SELECT bla FROM blub) Jedoch finde ich es per query einfach übersichtlicher und kürzer zu schreiben.

    Die Prepared Statement methode ist anscheinend schneller und zumindest beim eintragen von Benutzerdaten in die Datenbank sicher gegen sql-injection. Jedoch brauch ich diese sicherheit auch beim abfragen von Daten aus der Datenbank ?

    Kurz: würdet ihr beim auslesen von Daten Prepared Statements dem query vorziehen ? wenn ja, warum ?

    Gruß Elcon

  • #2
    Zitat von Elcon Beitrag anzeigen
    Jedoch brauch ich diese sicherheit auch beim abfragen von Daten aus der Datenbank ?
    Du solltest nicht zwischen eintragen und auslesen unterscheiden sondern zwischen Usereingaben und keine Usereingaben.
    [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

    Kommentar


    • #3
      Ja, verwende überall Prepared Statements, so wie tkausl schrieb. Und ja, du bist mit PS tatsächlich schneller dran, da diese Statements vom MySQL-Server nur einmal geparsed werden und danach bereits im Query-Cache vorliegen.
      [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

      Kommentar


      • #4
        Zitat von ChristianK Beitrag anzeigen
        Und ja, du bist mit PS tatsächlich schneller dran, da diese Statements vom Server nur einmal geparsed werden
        Keine Regel ohne Ausnahme. Nicht immer sind prepared Statements schneller.
        PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

        Kommentar


        • #5
          Zitat von Elcon Beitrag anzeigen
          Man kann per Prepared Statement ja auch genau so gut daten aus der datenbank auslesen (also SELECT bla FROM blub) Jedoch finde ich es per query einfach übersichtlicher und kürzer zu schreiben.
          Kürzer wird der Quellcode, ja. Aber er wird nicht übersichtlicher. Außerdem versteckt ->query() diverse Feineinstellungsmöglichkeiten, die dir PDOStatement, ->bindParameter() und Co. bieten.

          Die Prepared Statement methode ist anscheinend schneller ...
          Nein ist sie nicht. Aber wenn die Prepared Statements nicht von PDO emuliert werden, kann der Datenbankserver sie zur weiteren Verwendung zwischenspeichern. Wiederholte Aufrufe mit anderen Argumenten ("Parametern") sind so "schneller" (effizienter oder *wasauchimmerer*) möglich, bspw. mehrere INSERTs in die selbe Tabelle.

          und zumindest beim eintragen von Benutzerdaten in die Datenbank sicher gegen sql-injection.
          Die Sicherheit entsteht durch die Parametrisierung von Datenbankanfragen. Weil du Benutzereingaben ("Argumente", "Parameter") nicht mehr direkt in den Query-String reinpappst, sondern diese Aufgabe jemanden überlässt, der Datentypen und Werte prüfen und entsprechende Sicherungs-Maßnahmen ergreifen kann, wird quasi das Problem "menschliches Versagen" (des Programmierers) ausgeschlossen. PDOStatement kann das ganz gut.

          Jedoch brauch ich diese sicherheit auch beim abfragen von Daten aus der Datenbank?
          siehe tkausl's Antwort.
          Ergänzend: Du brauchst diese Sicherheit immer, wenn Benutzereingaben im Spiel sind -- auch wenn keine Datenbank beteiligt ist.

          Kurz: würdet ihr beim auslesen von Daten Prepared Statements dem query vorziehen? wenn ja, warum?
          Ja. (Außer vielleicht für einmalige Bastelarbeiten)

          Weil sie unter PHP die einzige Möglichkeit darstellen, das Query-String-"Template" und die dazugehörigen Argumente getrennt zu behandeln.
          Außerdem ersparen sie mir, die Feinheiten des "Escaping" und "Quoting" von Argumenten jedes Datenbanktreibers auswendig lernen zu müssen.
          Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

          Kommentar


          • #6
            Zitat von ChristianK Beitrag anzeigen
            Ja, verwende überall Prepared Statements, so wie tkausl schrieb. Und ja, du bist mit PS tatsächlich schneller dran, da diese Statements vom MySQL-Server nur einmal geparsed werden und danach bereits im Query-Cache vorliegen.
            Das ist falsch. Ein Prepared Statment ist immer nur für die aktuelle Verbindung gültig. Gecacht werden ggf. nur die Ergebnisse der Abfragen. Bei einmaliger Ausführung ist ein normaler Query schneller, erst bei mehrmaliger Ausführung entsteht ein Geschwindigkeitsvorteil. Wobei schneller relativ ist. Wenn Datenbank und Client auf dem selben Host laufen fällt das in die Kategorie:
            PHP-Code:
            echo $string1.$string2vs echo $string1,$string2
            Wenn Datenbank und Client getrennt laufen kommt auf jedenfall einmal zusätzlich die Netzwerklatenz dazu. Das kann je nach Setup schon ins Gewicht fallen.

            Auch zu beachten ist, dass wo Prepared Statment drauf steht nicht unbedingt Prepared Statments drin sind. PDO emuliert bei Mysql standardmässig Prepared Statments, obwohl die Dokumentation etwas anderes sagt. Grade wenn diese aus Performancegründen eingesetzt werden ist das ärgerlich.

            *edit*
            Die Sicherheit entsteht durch die Parametrisierung von Datenbankanfragen. Weil du Benutzereingaben ("Argumente", "Parameter") nicht mehr direkt in den Query-String reinpappst, sondern diese Aufgabe jemanden überlässt, der Datentypen und Werte prüfen und entsprechende Sicherungs-Maßnahmen ergreifen kann, wird quasi das Problem "menschliches Versagen" (des Programmierers) ausgeschlossen.
            Ganz vorsichtig mit solchen pauschal Aussagen! Wenn du ein Query dynamisch erstellen willst kann das deftig nach hinten losgehen. Bestes Beispiel: ORDER BY ...

            Kommentar


            • #7
              Zitat von erc Beitrag anzeigen
              Ganz vorsichtig mit solchen pauschal Aussagen!
              Ich dachte, ich hätte genügend Wortmaterial reingesteckt, was die Pauschalität wieder relativeren würde ...

              Wenn du ein Query dynamisch erstellen willst kann das deftig nach hinten losgehen. Bestes Beispiel: ORDER BY ...
              Wenn das nicht zuweit vom Ursprungsthema wegführt: Wo siehst du da das Problem? ORDER BY erlaubt doch nur Spaltennamen und die sind "Identifier", für die weder PDO- noch MySQLi-Statements Platzhalter erlauben.
              Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

              Kommentar


              • #8
                Bezüglich der Emulierung gibt es jedoch auch widersprüchliche Angaben. Einerseits wird eine Emulation in der Doku erwähnt, anderseits findet man auch Dokumentationsteile, die wieder das Gegenteil behaupten. Ich habe die Ref leider nur nicht gerade zur Hand. Bei Bedarf kann ich die jedoch suchen.
                [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                Kommentar


                • #9
                  Zitat von fireweasel Beitrag anzeigen
                  Ich dachte, ich hätte genügend Wortmaterial reingesteckt, was die Pauschalität wieder relativeren würde ...
                  Ja, hängen bleibt aber: "prepared statments automatisch sicher".

                  Zitat von fireweasel Beitrag anzeigen
                  Wo siehst du da das Problem? ORDER BY erlaubt doch nur Spaltennamen und die sind "Identifier", für die weder PDO- noch MySQLi-Statements Platzhalter erlauben.
                  Genau das ist das Problem.

                  PHP-Code:
                  $db->prepare("SELECT * FROM foo WHERE category = ? ORDER BY ".$_GET['order_by'])->execute($_GET['category']); 
                  PS: auch wenn das harmlos aussieht, mit entsprechender kreativität kann man damit auch Daten auslesen/erraten.

                  @ChristianK es wird in allen Version bei PDO/Mysql emuliert... das Thema gabs schonmal hier im Forum.

                  Kommentar


                  • #10
                    Zitat von erc Beitrag anzeigen
                    PHP-Code:
                    $db->prepare("SELECT * FROM foo WHERE category = ? ORDER BY ".$_GET['order_by'])->execute($_GET['category']); 
                    Das wäre dann aber wieder "Zusammenpappen" des Query-Strings (per .-Operator). Das stört mich an PDO (und MySQLi), dass man da keine Platzhalter für Identifier benutzen darf.

                    Sonst könnte man nämlich so was bauen wie:

                    PHP-Code:
                    $db->prepare('SELECT * FROM foo WHERE category = ? ORDER BY ?')
                        ->
                    bindValue(1$_GET['category'], PDO::PARAM_STR)
                        ->
                    bindValue(2$_GET['order_by'], PDO::PARAM_IDENTIFIER)
                        ->
                    execute();
                    // oder
                    $db->prepare('SELECT * FROM foo WHERE category = ? ORDER BY ?')
                        ->
                    bindValue(1$_GET['category'], PDO::PARAM_STR)
                        ->
                    bindIdentifier(2$_GET['order_by'])
                        ->
                    execute(); 
                    Da fehlt natürlich noch die Einschränkung der erlaubten Werte für "order_by". Aber SQL-Injections könnte man damit erstmal keine mehr erzeugen.
                    Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                    Kommentar


                    • #11
                      zum Thema Emulation:
                      Soweit ich das verstanden habe ist dafür das Attribut PDO::ATTR_EMULATE_PREPARES zuständig.
                      Dies sollte per Default auf false stehen, damit bei Nutzung von Prepared Statements diese sicher sind.
                      Bei einigen speziellen SQL-Anweisungen kann es zu Problemen kommen, die durch ein Setzen von PDO::ATTR_EMULATE_PREPARES auf true umschifft werden. Dann muß aber der Nutzer von sich aus sicherstellen, dass SQL-Injektion ausgeschlossen ist.

                      Zum Thema Validieren und Maskieren von Feld- und Tabellennamen nochmal der Link zu einer Diskussion hier im Forum.

                      Kommentar


                      • #12
                        Ja. Dadurch müssen jedoch auch automatisiert emulierte Statements gleich sicher sein wie echte Prepared Statements - in der Annahme, dass Skript wurde auf echte PS eingestellt. Weil du erhälst von PDO keinerlei Information, welcher Modus denn nun genutzt wird.
                        [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                        Kommentar


                        • #13
                          Erstmal Danke für die Vielen Antworten.

                          Auch wenn ich mindestens 80% davon noch nicht wirklich verstehe

                          Ich fasse für mich als Anfänger mal zusammen was ich verstanden habe :

                          Preparef Statements :

                          - Überall dort, wo Benutzer eingaben im Spiel sind (INSERT, UPDATE, SELECT und DELETE)
                          - Sind nur bei größerem Umfang der Daten wirklich schneller
                          - mehr möglichkeiten zur präzisierung

                          Daher werde ich sie einfach sicherheitshalber überall verwenden und mich erstmal intensiv mit dem thema Sicherheit auseinandersetzen bevor ich weiter mache an meinem Projekt.

                          Mir ist zum Beispiel aufgefallen dass man ja genauso gut z.B. Javascript-Code in die eingabefelder eingeben könnte oder auch html.

                          Habe erst gedacht ich verwende PS und zusätzlich mysqli_real_escape_string aber das erschien mir irgendwie doppeld gemoppeld. Ausserdem werden bei mysqli_real_escape_string Zeichen wie Hochkommas im Namen mit escaped.

                          Habe mir daher folgende funktion zusammen "gegoogelt" :

                          PHP-Code:
                          function fixall($text){
                              
                          $text strip_tags($text);
                              
                          $text htmlspecialchars($text);
                              
                          $text trim($text);
                              
                          $text stripslashes($text); 
                              return 
                          $text;

                          diese ebenutze ich für alle Texteingaben und für numerische werte die funktion intval().

                          Ist das so Inordnung ?

                          Kommentar


                          • #14
                            Zitat von Elcon Beitrag anzeigen
                            Ist das so Inordnung ?
                            Nein. Du kannst nicht einfach mit einem Rundumschlag alle potentiell möglichen Kontextwechsel erschlagen, du musst immer genau den Kontextwechsel behandeln der gerade auftritt (beim Wechsel nach HTML z.B. htmlspecialchars()).

                            Kommentar


                            • #15
                              Danke für den Link.

                              Kommentar

                              Lädt...
                              X