Vorraussetzung für die Klasse ist PHP 5 und ein installiertes MySQLi.
Das Problem bei vielen Anwendungen ist, dass Variablen in Datenbankabfragen nicht oder unzureichend abgesichert sind.
$result = $database->query("SELECT * FROM news WHERE foo = '".$_GET['foo']."' AND bar = '".$_GET['bar']."';");
Hier wird angenommen, dass aus der Funktion bar() keine gefährlichen Daten zurückgegeben werden. Dies erfordert jedoch Wissen über den Inhalt der Funktion. Da sich Funktionen vor allem bei mehreren Entwicklern schnell ändern können, kann dies nicht sichergestellt werden.
$foo = 'foo';
$bar = bar();
$result = $database->query("SELECT * FROM news WHERE foo = '".$database->real_escape_string($foo)."' AND bar = '".$bar."';");
Es ist auch zu sehen, dass Variablen mit der Funktion addSlashes() versucht werden zu sichern. Auch wenn diese Funktion vielleicht ein sehr ähnliches Ergebnis liefert, so ist diese jedoch nicht ausreichend und damit ungeeignet.
$foo = 'foo';
$bar = 'bar';
$result = $database->query("SELECT * FROM news WHERE foo = '".addslashes($foo)."' AND bar = '".addslashes($bar)."';");
Dies ist zwar Sicher, erzeugt jedoch schnell viel und unleserlichen Code.
$result = $database->query("SELECT * FROM news WHERE foo = '".$database->real_escape_string($foo)."' AND bar= '".$database->real_escape_string($bar)."';");
Die Klasse MySQLi wird um zwei Methoden erweitert, die sich um das Escapen von Variablen kümmern. Diese Verhalten sich vom Syntax wie die Funktionen printf(), sprintf() oder vsprintf() und dürften somit vielen Entwicklern bekannt sein.
Grundsätzlich werden alle Variablen die in einem Query benutzt werden ohne Ausnahme escaped. Jede Ausnahme ist ein Sicherheitsproblem!
class Blar_Database_MySQL extends MySQLi
{
public function queryf()
{
$args = func_get_args();
$query = array_shift($args);
return $this->vqueryf($query, $args);
}
public function vqueryf($query, $args)
{
$args = array_map(array($this, 'real_escape_string'), $args);
$query = vsprintf($query, $args);
return $this->query($query);
}
}
Als Platzhalter für die Werte können folgende Angaben verwendet werden:
Der Platzhalter %f für Floats sollte nicht verwendet werden, da dieser von der eingestellten Locale abhängig ist und somit falsche Ergebnisse liefern kann.
Der Verbindungsaufbau erfolgt unverändert wie bei MySQLi:
$database = new Blar_Database_MySQL('hostname', 'username', 'password', 'database');
Ein einfacher Query ohne Variablen
$result = $database->query("SELECT * FROM news ORDER BY created DESC LIMIT 10;");
Ein Query mit einer Variable:
$id = 42;
$result = $database->queryf("SELECT * FROM news WHERE id = %u;", $id);
Ein Query mit mehreren Variablen:
$foo = 1;
$bar = 2;
$result = $database->queryf("SELECT * FROM news WHERE foo = %u AND bar = %u;", $foo, $bar);
Ein Query mit mehreren Werten aus einem Array
$foobar = array('foo', 'bar');
$result = $database->vqueryf("SELECT * FROM news WHERE foo = '%s' AND bar = '%s';", $foobar);
Warum werden keine Prepared-Statements verwendet?
Prepared-Statements sind zwar ähnlich sicher wie die oben genannte Erweiterung zu MySQLi, haben jedoch in der aktuellen Umsetzung von MySQLi eine grauenhafte Syntax. Ausserdem gibt es bei älteren Versionen des MySQL-Servers das Problem, dass der Query-Cache nicht mit Prepared-Statements funktioniert und damit eine niedrigere Performanze erzielt wird.
Dieses Dokument ist unter einer Creative Commons-Lizenz lizenziert.
Dokument wurde zuletzt am Samstag den 13. Juni 2009 um 22:55 Uhr aktualisiert.