dedlfix: MySQL Loginsystem

Beitrag lesen

Hi!

DBConnection::query("SELECT foo FROM bar WHERE bar.foo=?0 AND bar.x=?1", array($_POST['id'], $_POST['name']), array(DBConnection::NUMBER, DBConnection::LITERAL));
Das ist unsicher wenn du nicht garantieren kannst, dass beispielsweise $_POST['id'] wirklich eine Zahl ist. Üblicherweise ist nämlich alles in den EGPCS-Variablen vom Typ String.
Warum das? Ich parse das doch per intval() als Zahl.

Stimmt, dass das intval() im weiteren Verlauf nimmt die Unsicherheit raus. Da hab ich hier zu schnell gemeckert.

Wenn das tatsächlich ein String ohne Zahl als erstes Zeichen einlese, dann wird 0 zurückgegeben. Ist damit ein Problem verbunden? Sollte ich dann wohl auch eine Exception werfen, wenn das eigentlich numerisch erwartete Argument nicht numerisch ist?

Ich würde mir aus der Sicht von query() da keine Gedanken weiter machen. Wenn jemand Mist eingibt, kann er nicht erwarten, das was Sinnvolles rauskommt, Hauptsache es entsteht keine Sicherheitslücke. Natürlich kann man sich mit einer Exception beschweren, aber was soll's? Wenn jemand die Eingangsdaten auf fachliche Plausibilität prüfen möchte/muss, dann soll er das vorher tun.

Was dann bleibt, ist den Unterschied zwischen String und Identifier festzustellen. Ich würde das mit unterschiedlichen Platzhaltern realisieren, zum Beispiel: ?ziffer und ?!ziffer. Jedenfalls so, dass ? weiterhin als Platzhaltereinleitung steht, alle anderen Zeichen sind mehr oder weniger schon als normaler Operator verbraucht.
Dann würde ich aber vsprintf() nicht mehr verwenden können, da der das ganze ja anders handhabt. Damit wäre wohl meine Bearbeitung des Queries korrekt?

Ja, kannst du so lassen.

Eigentlich meint ich damit, dass ich dem Administrator mitteile, dass etwas falsch ist. So ähnlich wie die Log-Dateien vom Apache.

Als Idee hätte ich im Angebot, mit den Konfigurationsdaten ein optionales Callback zu übergeben. Beim Feststellen eines Fehlers würde ich zuerst bei is_callable() vom Callback selbiges mit detaillierter Information aufrufen und dann die allgemeine Exception werfen. In der Callback-Funktion kann dann was auch immer zur Admin-Benachrichtigung stehen.

[...] wusste aber nicht wie eine Exception bei tieferen Funktionsaufrufverschachtelungen reagiert.

Sie geht schnurstracks den Aufruf-Stack nach oben, alles andere ignorierend, bis irgendwo in einem ein try-Block ein passendes catch sie fängt.

Dazu würde mich auch noch einmal interessieren, warum das eigentlich per "Lazy Connect" stattfinden soll. Wenn die Init() aufgerufen wird, dürfte doch eigentlich klar sein, dass früher oder später eine DB-Verbindung benötigt wird. Warum dann nicht also gleich die Verbindung aufbauen und später dafür sich nicht mehr darum kümmern müssen?

Ohne Lazy Connect musst du vorher wissen, ob wirklich eine DB-Verbindung gebraucht wird. Kann man so machen. Dann musst du aber zu jedem Query-Aufruf sichergestellt haben, dass Init aufgerufen wurde. Und wenn du mehr als ein Query hast, die an unterschiedlichen Stellen der Programmlogik stehen und nichts voneinander wissen, musst du irgendwie das Init koordinieren. Ich würde das Init einfach auf Verdacht am Scriptanfang oder in einer allgemeinen Initialisierungsphase aufrufen. Es ist je erst einmal nicht mehr als eine Variablenzuweisung, was selbst bei Nichtverwendung so gut wie nichts kostet.

Ich würde allerdings die Connect-Logik anders als bei dir umdrehen. Pseudocode:

if (!self::$db) { // keine Verbindung vorhanden
  if (!konfigurationsdaten vorhanden)
    Exception
  $self::db = connect...;
}
return $self::db;

Wenn die Verbindung da ist, wunderbar, rausgeben und fertig. Konfigdatencheck brauchen wir nur, wenn sie erst noch aufgebaut werden muss.

Lo!