Grundlegend brauch man sich um etwas besser zu machen nur die Reihe schlechter Beispiele (phpBB, websvn, ...) anschauen, um anhand des Quelltextes über verbesserungen nachzudenken.
Drei wesentliche Probleme, die dabei immer wieder kehren, sind folgende:
- Sicherheit von Datenbankzugriffen und Schutz gegen ungültige Benutzereingaben
- Skalierbarkeit und Erweiterbarkeit der Anwendung (u.a. auch Anpassbarkeit durch Plugins
- Lesbarkeit und Dokumentation des Quelltextes der Anwendung
3. ist trivial. phpBB (v2) anschauen, sollte alles erklären. Zur Dreier will ich mich nicht äußern.
2. sollte auch klar sein, was gemeint ist. Ich führ's aber mal kurz mit aus, was ich speziell damit meine: Die meisten Systeme gehen davon aus, dass man entweder Änderungen direkt im Source vornehmen muss (phpBB), oder allein an definierten Schnittstellen (Yoomla!). Erstere Kategorie ist für flexible Systeme per Definition nicht zu gebrauchen (auch wenn die EE doch anders als phpBB (aber dennoch gleich) aussieht. Zweiteres bietet genau dann Einschränkungen, wenn man Änderungen vornehmen will, für die keine Schnittstelle definiert ist. Hier kann man z.B. ansetzen, um von Grund auf zu sagen: "Alles ist Plugin, was nicht für den Kern notwendig ist". D.h. es gibt genau 2 Dinge, die für den Kern von Relevanz sind: 1. Die Plugin-Loader-Schnittstelle, um das Definieren von Plugins zu erlauben UND die Integrationsroutinen, die das Binden von Funktionalität an den Kern erlauben. 1. ist trivial, 2. folgt aus der Tatsache, dass man seinem System ja die Möglichkeit geben muss, mit einem Plugin zu kommunizieren.
1. ist ein generelles Problem jeder Anwendung, da aber PHP an sich ein Bug ist (bestimmte Features funktionieren nur mit bestimmten Revisionen und solche Scherze), muss man für die Überprüfung seiner Eingaben besondere Sorgfalt walten lassen. Auch immer wieder berüchtigt sind in PHP die SQL-Injections, für die es im Wesentlichen 2 Ansätze gibt:
1. Nutzung von Prepared Statements (was nicht alle Datenbankschnittstellen unterstützen)
oder
2. Schreiben eines eigenen Datenbank-Interfaces, was die Codierung der Eingaben für den Benutzer transparent erledigt.
Letztere Möglichkeit ist zwar in erster Linie eine Einschränkung (Verbot der Durchführung von SQL durch den Benutzer), bietet aber einige wesentliche Vorteile:
- Datenbankunabhängigkeit
- Datenencodierung und zentrale Schutzmaßnahmen
- Abstraktion der Aufgaben und gepufferte Verarbeitung:
Man Überlege sich einmal:
[code:1:33458f71c6="
PHP-Code: Klassisch:"]
$c = mysql_connect();
$success = mysql_query("SELECT $bad from $worse WHERE $evil='$malicious';");
while($attack = mysql_fetch_assoc($success))
{
echo eval($attack['bad']);
}
[/code:1:33458f71c6]
durch folgende Alternative zu ersetzen:
[code:1:33458f71c6="
PHP-Code: Alternativ:"]
$c = DB_Connection('config_runtime');
$table = $c->defaultdb->desired_table;
$table->filters->add('filtercol', $probably_malicious_value, EQUAL);
foreach($table as $rowid => $resultrow)
{
echo html_special_chars($resultrow->output_column);
}
[/code:1:33458f71c6]
Was ist der Unterschied: Während ich bei ersterem Source jeden prügeln würde, der auch nur im Ansatz versucht sowas zu schreiben (Extrembeispiel
), gibt es im zweiten Fall einige Fehler, die man gar nicht machen kann, sowie sogar einige Funktionen, die man im ersten Beispiel mühevoll per Hand ergänzen müsste:
- Im zweiten Beispiel kann man anhand einer Variable\Konstante die gesamte Datenbank-Verbindung austauschen
- Der Verbindungsaufbau erfolgt unabhängig vom Datenbank-System
- Datenbank-Objekte kapseln direkt die gewünschten Informationen ohne Umweg über andere Klassen oder Funktionsaufrufe
- Eine Encodierung bösartiger Daten wird von der Datenbank in der Form erledigt, wie sie von dieser benötigt wird (z.B. bei der Filterung)
- Man kann die gesamte Funktionalität der Datenbank nutzen, ohne die Details der Implementierung zu kennen (vgl. Abfragen vorhandener Tabellen MySQL vs. Oracle
)
- Bessere Ausnutzung der Möglichkeiten von PHP
- Erhöhung der Übersichtlichkeit
P.S.: Mit einem Kumpel arbeite ich derzeit an einer Umsetzung eines DBAL (Database Abstraction Layer), der ähnlich wie das zweite Beispiel zu programmieren geht. Teilweise ist das Vorgehen dabei auch von den Delphi-Datenbank-Klassen inspiriert (z.B. in BEzug auf Joins
) Wenn wir soweit sind, können wir die Sources gern online stellen.
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.