PHP/Tutorials/Formulare

Aus SELFHTML-Wiki
< PHP‎ | Tutorials
Wechseln zu: Navigation, Suche

Sie können Webformulare benutzerfreundlicher gestalten, indem Sie sie schon clientseitig validieren und so Benutzer frühzeitig auf Eingabefehler hinweisen. Trotzdem müssen alle Eingaben serverseitig noch einmal geprüft werden, um zu gewährleisten, dass die Daten für eine spätere Verarbeitung geeignet sind und um die Gefahr von XSS-Angriffen auszuschließen.

Dieser Artikel versteht sich als Ergänzung zum Kurs zur Erstellung von Formularen in HTML. Von dort werden zwei Anwendungsfälle beispielhaft aufgegriffen:

  1. einfache Suche
  2. Bestellformular


GET und POST empfangen in $_GET und $_POST

Um die mit einem Formular versandten Daten mit PHP auszuwerten, muss man verstehen, dass PHP bereits eine Infrastruktur zum Empfang solcher Daten bereitstellt. Da Browser gegenwärtig Formulardaten nur mit den HTTP-Methoden GET und POST versenden, finden sich in PHP so empfangene Daten in den superglobalen Variablen $_GET und $_POST. In diesen superglobalen Variablen sind die Schlüssel-Wert-Paare in Form eines assoziativen Arrays abgelegt.

Wenn im action-Attribut bereits ein URL-Parameter notiert steht, das Formular aber mittels der POST-Methode versandt werden soll, so finden sich auf PHP-Seite sowohl in $_GET – obwohl die Anfrage nicht mit der GET-Methode übermittelt wurde, als auch in $_POST Schlüssel mit Daten. Es ist allerdings nicht besonders ratsam, die beiden Möglichkeiten, Parameter zu übergeben, auf diese Art zu vermischen.

Wann ist GET oder POST zu verwenden?

Regeln

Die Wahl der Übertragungsmethode hängt, will man es richtig machen, nicht etwa von der Präferenz des Programmierers ab, sondern folgt eigentlich ganz einfachen Regeln:

  1. Werden durch den Request lediglich andere Daten als Antwort empfangen, so ist die GET-Methode die richtige Wahl. GET wird auch als „sichere“ Methode bezeichnet, weil sich am Zustand des Servers nichts ändern sollte.
  2. Werden durch den Request Daten auf dem Server verändert, ist die POST-Methode die richtige Wahl.
  3. Werden Daten für Logins, insbesondere Passwörter übermittelt, dann ist nur POST die einzig richtige Wahl.

Gründe

Die Gründe sind ebenso einfach wie die Regeln. Nehmen wir zuerst GET:

GET-Parameter stehen in der URL

Es ist bei der GET-Methode unerheblich, ob Sie tatsächlich das Formular eines Browsers verwendet haben, oder ob sie die URL http://example.org/search.php?search=SELFHTML+Wiki als Link angeklickt oder als Bookmark aufgerufen haben. Aus serverseitiger Sicht ist das nicht nur für PHP stets das Selbe: Mit der Methode GET gesendete Formulardaten werden in URL-Parameter verwandelt und stehen dann auf dem Server in $_GET zur Verfügung.

Also würde der Browser aus einem Formular mit <input type="search" name="search"> etwas wie https://example.com/search.php?search=foo machen. Diese Abfrage kann zum einen als Link dargestellt und durch Proxy-Server oder den Browser gecached oder vom Benutzer als Bookmark gespeichert werden. Außerdem gibt es mit mod_rewrite (bei Apache) eine Möglichkeit, diesen URI z.b. als https://example.com/search/foo zu notieren, was in vielen Situationen vorteilhaft ist.

GET Zugriffe können gecached werden

Die Anforderung an GET-Zugriffe ist, nichts am Serverzustand zu verändern (von Log-Dateien oder ähnlichem einmal abgesehen). Deswegen ist bei solchen Zugriffen zu erwarten, dass sie deterministisch sind und die gleiche URL immer die gleiche Antwort liefert. Deswegen darf ein Server, der Browser und auch dazwischen liegende Cache-Speicher eine GET-Antwort in einem Cache zwischenspeichern und bei erneuter Anfrage auf die gleiche URL den Cache-Inhalt liefern, statt das PHP Script neu laufen zu lassen. Mit Hilfe von HTTP-Headern können Sie die Lebensdauer eines solchen Cache-Inhaltes beeinflussen (Cache-Control, Expires).

Datenänderungen niemals via GET

Nachteilig wäre es aber, GET in Abfragen zu verwenden, welche zu einer Änderung von auf dem Server gespeicherten Inhalten führen.

Nehmen wir an, der „Server“ wäre die unter http://router.lan erreichbare Konfigurations-Oberfläche eines WLAN-Routers wie beispielsweise einer Fritzbox und eine URL wie ...

Beispiel
http://router.lan/setPassword?newPassword=foobar
Natürlich sind sich (zumindest einige) die Hersteller solcher Geräte dieses Angriffs bewusst und treffen Gegenmaßnahmen.

... würde zu einer Änderung des im Router gespeicherten Passwortes führen. Dann könnte man einfach ein paar Millionen Mails aussenden, welche einen Link enthalten und dann mal sehen, wie viele zufällig an ihrem Gerät angemeldet waren und auf den Link geklickt haben. Dann könnte sich nämlich der Angreifer mit dem neuen Passwort anmelden und der Besitzer weiß nicht so recht warum.

Freilich ginge das auch gezielter, z. B. bei einem Bekannten, von dem man weiß, dass er einen bestimmten Router hat.

Dieser Angriff wird Cross Site Request Forgery genannt.

URLs stehen in Logfiles

Ein weiterer Umstand ist, dass die als GET-Parameter gesendeten Daten in Logfiles enthalten sind. Programmierer mit Verstand werden Passwörter niemals im Klartext ablegen. Sendet man jetzt aber per GET

https://example.com/login?user=foo&passwd=bar

dann steht das Passwort und der Benutzername in den Logfiles. Der Angreifer, der diese Logfiles erbeutet, findet vor, was in Sicherheitsfragen als "Bypass" bezeichnet wird: Aufwendig gehashte Passwörter in der Datenbank (sehr gut), verschlüsselte Übertragung (sehr gut) und dann der Klartext im Logfile (große Panne).

Ebenso könnte eine Datenänderung durch einen Link dazu führen, dass z. B. in einem Webshop immer wieder ein Artikel als "nicht verfügbar" gekennzeichnet wird. Z.B. Weil ein Mitarbeiter unwissentlich etwa eine solche URL als Favorit gespeichert hat:

https://example.com/angebote_verwalten.php?isbn=123456789&verfuegbar=0.

POST-Parameter werden nirgends archiviert

Wird POST als Methode verwendet und auch durch die Verwendung von $_POST erwartet, kann hier kein Schaden entstehen. Es gibt in PHP neben $_POST und $_GET auch noch $_REQUEST, welches die verwendete Methode nicht berücksichtigt, jedoch muss es im Einzelfall sehr gute Gründe geben, warum man letzteres anstelle von $_POST oder $_GET verwendet.

Beispiel einer seltenen Ausnahme

Allerdings kann es durchaus – selten – Umstände geben, welche GET als die zu wählende Methode erscheinen lassen. Nehmen wir mal an, der Inhaber eines Geschäftes will seine An- oder Abwesenheit mittels Anklicken eines Links oder Lesezeichens im Browser signalisieren:

https://example.com/kontakt.php?ChefIstDa=0 bzw. https://example.com/kontakt.php?ChefIstDa=1

könnte hier eine Variable für eine "Ampel" setzen. Das wäre in einem solchen Fall wohl auch im Hinblick auf die Folgen einer Fehlbedienung und Login-system bei einer Absicherung "noch vertretbar". Nur muss der Inhaber dann auch sehr diszipliniert handeln. Also brav den passenden Favorit bzw. Link aufrufen wenn er kommt oder geht. Zumindest die Aktivierung seiner Anwesenheitsnachricht könnte man automatisieren in dem die URL durch ein automatisch gestartetes Programm bzw. Skript aufgerufen wird sobald er sich an seinem Rechner anmeldet.

Das geht aber auch mit POST! Es spricht nichts dagegen, mittels JavaScript aus der URL die notwendigen Parameter zu ermitteln und die URL ohne diese über einen POST-Request mit den ebenso via POST versandten Parametern zu benutzen. Als Bookmarklet wäre eine JavaScript-basierte Lösung mit POST ebenso denkbar.

Beispiele:

einfache Suche

Suche mit GET
<form action="http://example.org/search.php">
  <p>
    <label>Suchbegriff <input name="search"></label>
    <button>finden</button>
  </p>
</form>
Nehmen wir an Sie geben im Textfeld "SELFHTML Wiki" ein. Dieses Formular wird beim Versenden dieses Datum mit dem Schlüssel search verschicken. Da die GET-Methode (default) gewählt wurde, wird der Browser folgende Zielseite ansteuern: http://example.org/search.php?search=SELFHTML+Wiki. Der Name "search" des URL-Parameters search entspricht dem Wert im name-Attribut des Eingabeelements.
<?php
if (array_key_exists('search', $_GET)) {
  tue_was_mit($_GET['search']);
}
?>
Das PHP-Script prüft, ob in dem superglobalen Array $_GET ein Schlüssel namens search enthalten ist. Ist das der Fall, wird eine (in diesem Beispiel nicht definierte) Funktion namens tu_was_mit aufgerufen, die den empfangenen Suchbegriff, den Wert zum Array-Schlüssel search, übergeben bekommt. Das Pluszeichen entsteht dadurch, dass der Browser das Leerzeichen zwischen "SELFHTML" und "Wiki" für den URL-Kontext passend maskieren muss. Der Wert von $_GET['search'] enthält kein Pluszeichen mehr, sondern stattdessen wieder das Leerzeichen.

Bestellformular mit komplexeren Eingabemöglichkeiten

komplexere Eingabemöglichkeiten
<form action="http://example.org/order.php">
  <fieldset>
    <legend>Ware</legend>
    <ul>
      <li>
          <label for="article-1">Schnittzeichnen in 40 Lektionen</label>
          <input id="article-1" name="article-1" type="number" value="0">
      </li>

      <li>Fernausbildung in Schnittmuster zeichnen</li>
      <li>
          <label for="article-2">Modul Hosen</label>
          <input id="article-2" name="article-2" type="number" value="0">
        <li>
          <label for="article-3">Modul Kleid, Jupe, Top</label>
          <input id="article-3" name="article-3" type="number" value="0">
      </li>
       <li>
          <label for="article-4">Modul Alltag: jacke, Bluse, Hemd </label>
          <input id="article-4" name="article-4" type="number" value="0">
      </li>
       <li>
          <label for="article-5">Modul Blazer</label>
          <input id="article-5" name="article-5" type="number" value="0">
      </li>
      </li>
    </ul>
  </fieldset>
  <fieldset>
    <legend>Bezahlung</legend>
    <p>
      <label for="payment">Art der Bezahlung</label>
      <select id="payment" name="payment">
        <option value="ae">American Express Card</option>
        <option value="master">MasterCard</option>
        <option value="visa">VISA</option>
        <option value="prepayment">Vorkasse</option>
      </select>
    </p>
    <p>
      <input id="email-receipt" name="email-receipt" type="checkbox">
      <label for="email-receipt">Quittung per E-Mail</label>
      <label for="email">an folgende Adresse</label>
      <input id="email" name="email" type="email">
    </p>
  </fieldset>
  <fieldset>
    <legend>Versand</legend>
    <dl>
      <dt>Lieferanschrift</dt>
      <dd>
          <ul>
            <li>
              <label for="recipient-name">Name</label>
              <input id="recipient-name" name="recipient-name">
            </li>
            <li>
              <label for="recipient-address">Anschrift</label>
              <input id="recipient-address" name="recipient-address">
            </li>
            <li>
              <label for="recipient-zip">PLZ</label>
              <input id="recipient-zip" name="recipient-zip">
              <label for="recipient-city">Ort</label>
              <input id="recipient-city" name="recipient-city">
            </li>
          </ul>
      </dd>
      <dt>Rechnungsanschrift</dt>
      <dd>
          <ul>
            <li>
              <label for="buyer-name">Name</label>
              <input id="buyer-name" name="buyer-name">
            </li>
            <li>
              <label for="buyer-address">Anschrift</label>
              <input id="buyer-address" name="buyer-address">
            </li>
            <li>
              <label for="buyer-zip">PLZ</label>
              <input id="buyer-zip" name="buyer-zip">
              <label for="buyer-city">Ort</label>
              <input id="buyer-city" name="buyer-city">
            </li>
          </ul>
      </dd>
    </dl>
  </fieldset>
  <fieldset>
    <legend>Zusatz</legend>
    <p>
      <label for="message">Ihre Nachricht an uns</label>
      <textarea id="message"></textarea>
    </p>
  </fieldset>
  <p><button>jetzt Kostenpflichtig bestellen</button></p>
</form>
Alle Eingabeelemente haben ein name-Attribut, damit ihr Inhalt als Schlüssel-Wert-Paar übertragen werden kann. Die einzige Besonderheit hier ist tatsächlich die Checkbox für die Quittung per E-Mail. Bei Checkboxen muss man serverseitig auf das Vorhandensein des Schlüssels prüfen, da bei nicht gesetztem Häkchen der Name der Checkbox unter den Schlüsseln fehlt.
// mögliche Zahlungsarten
$payment = array(
  'ae' => 'American Express Card',
  'master' => 'MasterCard',
  'visa' => 'VISA',
  'prepayment' => 'Vorkasse'
);

// Voreinstellungen für eine Bestellung
$order = array(
  'article-1' => 0,
  'article-2' => 0,
  'payment' => 'prepayment',
  'email-receipt' => false,
  'email' => '',
  'recipient-name' => '',
  'recipient-address' => '',
  'recipient-zip' => '',
  'recipient-city' => '',
  'buyer-name' => '',
  'buyer-address' => '',
  'buyer-zip' => '',
  'buyer-city' => '',
  'message' => ''
);

// für alle Schlüssel einer möglichen Bestellung
// nach geposteten Daten suchen
foreach ($order as $key => $value) {

  if (array_key_exists($key, $_POST)) {

    // nach Schlüssel differenzieren
    switch ($key) {

      // Bestellmenge: nur numerische Werte akzeptieren!
      case 'article-1':
      case 'article-2':
        $order[$key] = abs($_POST[$key]);
      break;

      // Zahlungsart: nur definierte Werte akzeptieren!
      case 'payment':
        if (array_key_exists($_POST[$key], $payment)) {
          $order[$key] = $_POST[$key];
        }
      break;

      // checkbox! Sein oder Nichtsein
      case 'email-receipt':
        $order[$key] = true;
      break;

      default:
        $order[$key] = $_POST[$key];
    }
  }
}
Nachdem die Datenstruktur einer Bestellung in der Variable $order erstellt und mit Voreinstellungen befüllt wurde, werden nun die Schlüssel dieses Arrays mit den Schlüsseln in $_POST abgeglichen. Bei Checkboxen will man eine "ja"/"nein"-Unterscheidung (true/false), daher ist hier nur wichtig, ob der Schlüssel in $_POST überhaupt vorhanden ist. Bei Bestellmenge und Zahlungsmethode müssen die Eingaben daraufhin geprüft werden, ob sie so erlaubt sind, bevor sie akzeptiert werden.
Beachten Sie: Getreu dem Motto "alle Benutzereingaben sind böse!" werden die Eingaben auf erlaubte Werte hin geprüft. Außerdem kümmert sich unser Script nur um Schlüssel, die auch erwartet werden, und kann durch unsinnige Schlüssel-Wert-Paare nicht angegriffen werden.

Ein Affenformular mit Validierung

Als Affenformular bezeichnet ein Formular, das nach dem Absenden dem Nutzer so lange wieder vorgesetzt wird, bis er es korrekt ausgefüllt hat.

Im folgenden Beispiel wird dabei auf die Validierung (E-Mail-Adresse, Passwortlänge und Vorhandenseinmüssen einer Eingabe) des Browsers zurückgegriffen, die Eingaben werden auf dem Server dennoch erneut überprüft, da man sich auf die Client-seitige Überprüfung nicht verlassen kann – der Nutzer kann sie leicht umgehen oder er benutzt einen Browser, der bestimmte Validierungs-Funktionen nicht unterstützt. Daher müssen Eingaben immer auf dem Server überprüft werden. Um den Komfort bei der Benutzung des Formulars zu verbessern und dem Nutzer sofort eine Rückmeldung geben zu können, sollte auch Client-seitig validiert werden.

Eine einzelne Prüfung erfolgt jedoch im Beispiel nur auf dem Server: Es wird überprüft, ob E-Mail-Adresse und das Passwort gleich sind. In der Praxis dürfte hier eine aufwändigere Prüfung auf schwache Passwörter erfolgen.

Affenformular mit Validierung
<?php
if(isset($_POST['sent'])) {
  $messages = [];

  // Eingaben überprüfen:
  if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
    $messages[] = 'Bitte prüfen Sie die eingegebene E-Mail-Adresse.';
  }
  if(($_POST['password1']??'') != ($_POST['password2']??'')) {
    $messages[] = 'Die eingegebenen Passwörter sind nicht gleich.';
  } elseif(!empty($_POST['email']) && $_POST['email']==$_POST['password1']) {
    // In der Praxis würde man noch mehr Tests auf schlechte Passwörter durchführen:
    $messages[] = 'Die E-Mail-Adresse darf nicht gleich dem Passwort sein.';
  }
  if(mb_strlen($_POST['password1']) < 8) {
    $messages[] = 'Das eingegebene Passwort ist zu kurz.';
  }

  if(empty($messages)) {
    // Registrierung ausführen...
    // Erfolg vermelden und Skript beenden, damit Formular nicht erneut ausgegeben wird
    die('<div class="success">Herzlichen Glückwunsch, Ihr Benutzeraccount wurde angelegt.</div>');
  } else {
    // Fehlermeldungen ausgeben:
    echo '<div class="error"><ul>';
    foreach($messages as $message) {
      echo '<li>'.htmlspecialchars($message).'</li>';
    }
    echo '</ul></div>';
  }
}
?>
<form method="post">
  <ul>
    <li>
      <label>E-Mail
        <input name="email" type="email"
         value="<?=htmlspecialchars($_POST['email']??'')?>" required>
      </label>
    </li>
    <li>
      <label>Passwort
        <input name="password1" type="password"
         value="<?=htmlspecialchars($_POST['password1']??'')?>" minlength="8" required>
      </label>
    </li>
    <li>
      <label>Passwort wiederholen
        <input name="password2" type="password"
         value="<?=htmlspecialchars($_POST['password2']??'')?>" minlength="8" required>
      </label>
    </li>
    <li>
      <button name="sent" value="1">Registrieren</button>
    </li>
  </ul>
</form>
Das Skript validiert die Eingaben und schreibt die Fehler in ein Array $messages. Enthält das Array Einträge, so ist mindestens eine Eingabe fehlerhaft, die Meldungen werden ausgegeben und das Formular erneut angezeigt. Enthält es hingegen keine Fehler, so war die Überprüfung erfolgreich, es wird eine Erfolgsmeldung ausgegeben und die Bearbeitung des Skripts abgebrochen.

Mehrfachauswahlen

Will man einen Fall bearbeiten, bei dem ein Benutzer mehrere Optionen auswählen kann, die später im PHP-Script ohnehin in einer Array-Struktur abgelegt werden, so kann man sich ein Feature von PHP zu eigen machen, nämlich die Sonderbehandlung von eckigen Klammern in Schlüsselnamen von Schlüssel-Wert-Paaren:

Mehrfachauswahl
<form method="post">
<fieldset>
  <legend>Ihre Pizza-Bestellung</legend>
  <p>
    Größe
    <label><input name="groesse" type="radio" value="S"> klein</label>
    <label><input name="groesse" type="radio" value="M"> mittel</label>
    <label><input name="groesse" type="radio" value="L"> groß</label>
  </p>
  <p>Bitte wählen Sie die gewünschten Zutaten:</p>
  <ul>
    <li><label><input type="checkbox" name="zutaten[]" value="Salami"> Salami</label></li>
    <li><label><input type="checkbox" name="zutaten[]" value="Schinken"> Schinken</label></li>
    <li><label><input type="checkbox" name="zutaten[]" value="Paprika"> Paprika</label></li>
    <li><label><input type="checkbox" name="zutaten[]" value="Speck"> Speck</label></li>
  </ul>
</fieldset>
</form>
In der Zutatenliste tragen die input-Elemente alle den Namen "zutaten[]". Das verarbeitende PHP-Script wird im Array $_POST für den Schlüssel "zutaten" ein Array anlegen, sodass die zugehörige Struktur (bei passender Benutzereingabe) folgendermaßen aussehen wird:
$_POST = array(
  [groesse] => S
  [zutaten] => array(
    [0] => Salami
    [1] => Paprika
  )
)

Man könnte sich mit einer passenden Benennung aller input-Elemente die gesamte Bestellung in einen einzigen $_POST-Schlüssel verpacken:

Name-Attribute speziell für PHP
<form method="post">
<fieldset>
  <legend>Ihre Pizza-Bestellung</legend>
  <p>
    Größe
    <label><input name="bestellung[groesse]" type="radio" value="S"> klein</label>
    <label><input name="bestellung[groesse]" type="radio" value="M"> mittel</label>
    <label><input name="bestellung[groesse]" type="radio" value="L"> groß</label>
  </p>
  <p>Bitte wählen Sie die gewünschten Zutaten:</p>
  <ul>
    <li><label><input type="checkbox" name="bestellung[zutaten][]" value="Salami"> Salami</label></li>
    <li><label><input type="checkbox" name="bestellung[zutaten][]" value="Schinken"> Schinken</label></li>
    <li><label><input type="checkbox" name="bestellung[zutaten][]" value="Paprika"> Paprika</label></li>
    <li><label><input type="checkbox" name="bestellung[zutaten][]" value="Speck"> Speck</label></li>
  </ul>
</fieldset>
</form>
Das $_POST-Array hätte (wiederum bei passender Benutzereingabe) diese Struktur:
$_POST = array(
  [bestellung] => array(
    [groesse] => S
    [zutaten] => array(
      [0] => Salami
      [1] => Schinken
    )
  )
)
Hinweis:
Es bleibt eine Frage der Abwägung, inwiefern man im HTML-Code PHP-spezifische Eigenarten einfließen lässt, um dem Programmierer bei der serverseitigen Verarbeitung das Leben leichter zu machen, oder ob der HTML-Code unbedingt auch auf anderen Plattformen ohne PHP gleichermaßen verarbeitbar sein muss.

Erwartung an Daten formulieren

Ein Script, welches Formulardaten auswertet, muss dagegen gehärtet sein, dass ein Angreifer Daten schickt, die das Script so nicht erwartet, um es vielleicht zu einer Funktionsweise zu verleiten, die sich für andere Dinge ausnützen lässt, die nicht im Interesse des Seitenbetreibers sind.

Eine Härtung gegen ungewollte Daten und Datentypen gelingt leichter, wenn man im Script von einer klar formulierten Erwartung ausgehen, und die Daten gegen diese Erwartung abgleichen kann. Verwenden wir dazu das Beispiel einer Pizza-Bestellung von oben.

Erwartung an Formulardaten
$optionen = array(
  'groesse' => array('S', 'M', 'L')
  'zutaten' => array('Salami', 'Schinken', 'Paprika', 'Speck')
);

$bestellung = array(
  'groesse' => 'S',
  'selbstabholer' => false,
  'zutaten' => array()
);

foreach ($_POST as $key => $value) {

  switch ($key) {

    case 'groesse':
      if (in_array($value, $optionen[$key])) {
        $bestellung[$key] = $value;
      }
    break;

    case 'selbstabholer':
      $bestellung[$key] = true;
    break;

    case 'zutaten':
      if (is_array($value)) {

        foreach ($value as $zutat) {

          if (in_array($zutat, $optionen[$key])) {
            $bestellung[$key][] = $zutat;
          }
        }
      }
    break;

    default:
      // unerwartete Daten!
    break;
  }
}
Das $_POST-Array könnte alles Mögliche enthalten. Damit nun aber nur bekannte Größen oder Zutaten aufgenommen werden können, sind die möglichen Werte in einer entsprechenden Arraystruktur notiert. Auch ist für die Bestellung bereits eine Grundstruktur angelegt.

Die switch-Verzweigung regelt, wie genau zu verfahren ist:

  1. Bei der Größe wird der gepostete Wert mit den möglichen Größen im groessen-Unterarray verglichen und nur akzeptiert, wenn er darin enthalten ist.
  2. Bei Checkboxen wird nur dann überhaupt der Schlüssel übertragen, wenn das Häkchen gesetzt worden war. Deswegen kann im Falle von Selbstabholern zunächst der Standardwert false angenommen werden. Ist der Array-Schlüssel im $_POST-Array vorhanden, genügt es von false auf true zu ändern.
  3. Bei den Zutaten können Mehrfachnennungen sein. Deshalb wird hier der $_POST-Wert als Array behandelt und jeder seiner Einträge mit den möglichen Zutaten abgeglichen.

Wenn nun ein Angreifer Stördaten mitsendet, bei denen er sich erhofft, dass diese dann genau so auf der Rechnung stehen, dann sorgt unsere Vorgehensweise dafür, dass diese herausgefiltert werden. Die Webanwendung sollte genau deswegen vor der endgültigen Aufgabe der Bestellung in einer Übersichtsseite anzeigen, wie die Bestellung nun tatsächlich aufgenommen wurde, um diesem Filtereffekt Rechnung zu tragen.

Siehe auch

Tutorials

Referenz