Skrivet av lambdaN:
Hojj vlket helvete. Aja, då är väl sportlovet planerat
Om jag förstår rätt, så just nu gör jag
HTML -> PHP -> MYSQL
medans med MySqlI så blir det:
HTML -> PHP -> MYSQLI -> MYSQL
? Med andra ord, jag tappar inte databasen?
Just nu använder du den utdaterade modulen som heter Original MySQL API i PHP för att kommunicera med databasen MySQL.
I stället rekommenderas det att du använder modulen MySQLi för att kommunicera med databasen MySQL (eller PDO_MYSQL som är liknande).
Redan i PHP-manualens introduktionsavsnitt för den gamla MySQL-modulen så står det:
Citat:
This extension is deprecated as of PHP 5.5.0, and is not recommended for writing new code as it will be removed in the future. Instead, either the mysqli or PDO_MySQL extension should be used. See also the MySQL API Overview for further help while choosing a MySQL API.
Ett praktiskt exempel (inte fullständigt, inte ämnat för produktion, nätet svämmar över av mer utförlig information om skillnaderna mellan API:erna):
I stället för att du med det gamla API:t skriver en textsträng och kastar den rakt in i MySQL:s innersta via
// OBS! Exempel på hur en databasfråga INTE ska se ut:
mysql_query('UPDATE tabell SET namn="'.$_POST['namn'].'", alder="'.$_POST['alder'].'" WHERE id='.$_POST['id']);
så bör/kan/ska man med MySQLi skriva likt (rikligt kommenterat):
// Definiera för MySQL vad som är frågestruktur och vad som är indata. Indata
// markeras med placeholder '?'.
$query=$mysqli->prepare('UPDATE tabell SET namn=?, alder=? WHERE id=?');
// Definiera vilka datatyper som ska skickas in och vilka som är motsvarande
// PHP-variabler (s=sträng, i=integer=heltal).
$query->bind_param('sii', $_POST['namn'], $_POST['alder'], $_POST['id']);
// Nu har MySQL hunnit förbereda sig och frågan körs inte förrän nu med ett
// enkelt:
$query->execute();
// Om vi inte ska använda denna fråga mer så kan vi för ordnings skull köra
// (detta körs när PHP är klar med sidan likväl, kan nämnas)
$query->close();
MySQL kommer här "kompilera" queryn och förbereda sig för att ta emot själva frågan för att sedan köra den med "execute". Om många rader ska behandlas så snabbar detta upp saker då samma kompilerade fråga kan återanvändas (enkelt sagt; i praktiken hjälper cachefunktioner till med detta även om man inte själv säger till). Den stora fördelen är dock för de flesta bara att det nu är definierat vilka datatyper som ska in i vilka fält, om de inte stämmer så säger PHP till, och SQL-injektion är avvärjt (om man inte gör något särdeles dumt).
För att visa på sårbarheter som det första "dåliga" sättet att skriva på öppnar: låt säga att en användare i namnfältet skrivit
och kanske gjort en egen POST-request med id-fältet
Om du använder MySQLi så kommer namnet helt enkelt sättas till den strängen (inget säkerhetshål), och om `id`-fältet inte var ett heltal så skulle PHP säga till och stoppa transaktionen.
Om du skrivit som i det första naiva fallet ovan med gamla API:t så skulle användaren dels kunna ändra lösenordet genom en sidomekanism, och även möjligen (exemplet var bara en prototyp för att illustrera idén) ändra allas namn och lösenord till kalle:hej. Vad detta i praktiken gör beror på sidan i övrigt, men vi kan alla hålla med om att det inte är önskvärt.
Om det handlat om en DELETE-sats så skulle "1 OR 1=1"-liknande `id`-fält kunna rensa hela databasen.
Om det handlat om en SELECT-sats så skulle det kunna få allas uppgifter att skrivas ut till den som gjorde requesten, inklusive lösenord om de även gjorde en variant likt den i namnfältet för att påverka ytterligare fält.
Det var enkla exempel på SQL-injektion (kanske för enkla i praktiken, men de är som sagt bara tänkta att illustrera idén). För att ha ett någorlunda acceptabelt skydd med det utdaterade MySQL-API:t så skulle man kanske i stället skriva:
$namn = mysql_real_escape_string($_POST['namn']);
$alder = (int)$_POST['alder'];
$id = (int)$_POST['id'];
mysql_query('UPDATE tabell SET namn="'.$namn.'", alder='".$alder.'" WHERE id='.$id);
Några observationer angående detta sätt:
det blir lika mycket att skriva i detta enkla exempel, betydligt mer om frågan är mer komplicerad (mer indata)
det blir mindre tydligt vad som faktiskt händer i databasfrågan (i mer komplicerade exempel är detta ett reellt problem)
prestandan blir sämre än med prepared statements
extra tid och kod behöver tillbringas på att kontrollera indata och om man gör något fel här så öppnar man för attacker (hint: alla gör någon gång något fel här).
Är man "van" vid det gamla och snart försvunna sättet så kan det kännas bökigt att byta (det tyckte jag när jag först uppmärksammades på problematiken), men snabbt märker man att det nya sättet snarare tjänar tid, är mycket mer överblickbart och man kan sova bättre om nätterna; dels av säkerhetsskäl, men även då man inte riskerar att vakna upp och se att PHP tagit bort stödet för det gamla MySQL-API:t.
Som sagt: internet har mängder med mer information. Läs t ex de länkar till Stack Overflow som jag gav i förra posten för lite inblick. Fler länkar: