[Thread Prev][Thread Next]   >Date Index >Thread Index

Re: HTML-Formular CGI/DBI in MySQL DB schreiben - Kopfschmerzen

Thomas Linden - Sun Aug 26 18:44:23 2007

> my @Feldnamen = $cgi->param();

Nur als Tipp, so kannst Du die Werte schöner benutzen:

my %input  = map { $_ => $cgi->param($_) } $cgi->param;

Im Hash %input hast Du dann alle Eingaben bequem abgelegt.
 
>       foreach my $Feld (@Feldnamen) {
> 
> 
> my $sth = $dbh->prepare('INSERT INTO spieler ($Feld)
> VALUES('$cgi->param($Feld)')
>                 or die "Kann Daten nicht eintragen: " . $dbh->errstr;
> 
> $sth->execute;
> 
> }

Hier fuehrst Du pro Feld ein SQL Statement aus. Bei einer Spassanwendung
ist das womoeglich noch akzeptabel. In einer produktiven Anwendung, auf
die u.U. mehrere Hundert User gleichzeitig zugreifen schiesst Du Dir so
ins Knie.

Daher wuerde ich aus allen Feldern ein einziges SQL Statement
konstruieren. Ausserdem wuerde ich nur die Felder nutzen, die ich
brauche. Ein boeser User koennte Dir per CGI Daten schicken, die Du gar
nicht brauchst (und die Schaden anrichten koennten, siehe unten).

Daher zb so:

my @fields = qw(username address phone);
my $sql = "INSERT INTO spieler ";
my @values;
foreach my $field (@fields) {
  $sql .= "set $field . " = ?,";
  push @values, $input{$field};
}
chop $sql; # letztes Komma weg (geht mit map sicher besser...)

my $sth = $dbh->prepare($sql) or die "Prepare failed: " . $dbh->errstr;
$sth->execute(@values) or die "Insert failed: " . $dbh->errstr;


Sieht evtl. etwas kompliziert aus auf den ersten Blick. Was tun wir
hier? Zum einen verwenden wir nur die Felder, die wir auch in der
Tabelle haben. Zum anderen ueberlassen wir DBI das Quoting, was es
naemlich automagisch tut, wenn man im SQL Statement als Value ein ?
eintraegt und beim execute() die Werte uebergibt. Zugegeben, das chop()
ist unschoen, man haette auch einen sortierten Hash nehmen koennen oder
den Kram per map() vorbereiten koennen - aber hey, ich bin im Urlaub :)

Zu guter Letzt sei Dir empfohlen, zusaetzlich den Input zu validieren,
es gibt dafuer mehrere Module auf dem CPAN, zb. Data::Validate, um
sicherzustellen, dass in Deiner DB nur die Art Daten landet, die Du dort
haben willst. Beispielsweise sollte ein Username nur [a-zA-Z0-9]
enthalten, aber kein '. Wenn Du die Eingaben nicht validierst, kann ein
Angreifer per SQL Injection nicht nur Deine Daten veraendern, mit etwas
Geschick kann er sie auch auslesen.

Viel Spass ansonsten und Servus von der Ostsee :)


- Tom


Next: