Už dlouhou dobu porůznu vyvíjím webové aplikace, malé, velké i podivné nebo neužitečné. V posledním roce jsem se hodně zaměřil na bezpečnost dat a aplikací, proto bych zde rád publikoval něco, co na internetu najdete všude možně. Hůř se to pak hledá v aktualizované formě a nejhůř v češtině. Vše co zde dále uvedu slouží jako příklad a je třeba ledasco dotáhnout (design aplikace nebo čistotu kódu neřeším, jde mi o principy a postupy).
Ale budu moc rád za každé upozornění nebo případný zlepšovák. Co pro Vás nyní mám?
Jak se v PHP bezpečně spojit s databází a pracovat s ní.
V první části bych rád upozornil na fakt, že spojení s MySQL pomocí modulu mysqli (volím mysqli, protože se jedná o nejuniverzálnější a nejaktuálnější způsob připojení PHP k databázi – viz. php.net) může být objektově orientované (OOP) a procedurální. Celé PHP se pomalými krůčky sune k OOP, já ale zatím přežívám na procedurálním přístupu.
Příklad, který zde uvádím, je tedy využití mysqli modulu v PHP k připojení k databázi MySQL.
Připojení k samotné databázi
Připojení k samotné databázi probíhá velice snadno pomocí následujícího PHP kódu:
$mysqli = new mysqli('adresa-sql.serveru','uzivatelske-jmeno','uzivatelske-heslo*','nazev-databaze');
if ($mysqli->connect_error) {
die('Chyba : ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
}
V případě, že se nepovede spojit s databází, očekávejte chybové hlášení (pokud je máte v PHP zapnuty) s informací, co se nepovedlo.
SELECT – zobrazení dat z databáze
//Vysvětlivka 1
$archiv = "0";
//Vysvětlivka 2
$query = "SELECT id,nazev,hodnota FROM pokus1 WHERE smazano=?";
//následuje příprava dotazu
$statement = $mysqli->prepare($query);
//Vysvětlivka 3
$statement->bind_param('i', $archiv);
//proveď dotaz
$statement->execute();
//ulož výsledek dotazu (není nutné)
$statement->store_result();
//z vybraných hodnot (z hodnot v dotazu, opět postupně tak jak jsou v dotazu) utvoř proměnné
$statement->bind_result($id, $nazev, $hodnota);
//zpracování záznamů
while($statement->fetch()) {
print '<p>';
print $id.': ';
print $nazev.' / ';
print $hodnota;
print '</p>';
}
Vysvětlivky:
- pro demonstrační účely nastavuji proměnnou, kterou využiji v dotazu
- dotaz do SQL, všimněte si, že v klauzuli WHERE mám zadáno, že požaduji aby sloupec „smazano“ byl roven otazníku, otazník bude následně nahrazen proměnnou
- proces přípravy detekuje proměnné a ty je třeba programu vysvětlit, proces „vysvětlení“ má dvě části: v první části definujete jaký typ proměnné bude v příkazu (zástupné znaky : s = string, i = integer, d = double, b = blob) a po čárce (v druhé části) pak následuje výpis proměnných (opět v pořadí jako je v dotazu), které se mají doplnit
Výše vypsaný kód vypíše na jeden řádek data z databáze. Pokud chcete mít v dotazu více proměnných, kód bude vypadat takto:
$stav = "ok";
$mesto = "Praha";
$archivovano = 0;
$query = "SELECT id,prodejce,suma FROM prodeje WHERE stav=? AND mesto=? AND archivovano=?";
$statement = $mysqli->prepare($query);
$statement->bind_param('ssi', $stav, $mesto, $archivovano);
$statement->execute();
$statement->store_result();
$statement->bind_result($id, $prodejce, $suma);
print '<table>';
print '<tr colspan="3">Prodeje: '.$mesto.'</tr>';
print '<tr><th>ID záznamu</th><th>Jméno prodejce</th><th>Celkem prodal</th></tr>';
while($statement->fetch()) {
print '<tr>';
print '<td>'.$id.'</td>';
print '<td>'.$prodejce.'</td>';
print '<td>'.$suma.' CZK</td>';
print '</tr>';
}
print '</table>';
Z tabulky jsme vybrali výsledky všech prodejců z města „Praha“, kde indikátor záznamu je „ok“ a nejedná se o záznam archivovaný.
Krása „Prepared Statements“ spočívá v tom, že nemůže dojít k SQL Injection, tedy napadení webu tímto postupem. Všechny pokusy o injektáž SQL kódu budou zhaceny tím, že takto připravená proměnná již nebude akceptovat další SQL kód.
INSERT – vložení dat do databáze
Stačí upravit SQL dotaz a stejný kus kódu je použitelný i pro příkaz UPDATE nebo jiné přímé operace s tabulkami.
Vkládání dat do databáze probíhá už velmi podobně jako zobrazování, uvedu tedy přímo příklad.
$query = "INSERT INTO pokus1 (nazev,hodnota) VALUES(?, ?)";
$statement = $mysqli->prepare($query);
$statement->bind_param('ss', $promenna, $hodnota);
if($statement->execute()){
print 'Povedlo se! ID vloženého záznamu je : ' .$statement->insert_id .'<br />';
exit;
}else{
die('Chyba : ('. $mysqli->errno .') '. $mysqli->error);
}
Kód prostě vloží data do databáze nebo při selhání vypíše chybu.
Toto je krátká kuchařka pro základní připojení a dotazy do MySQL databáze pomocí PHP modulu mysqli. Připravuji ještě další článek o ochraně vstupů POST a GET, tedy při zpracování formulářů.
Budu moc rád za jakoukoliv zpětnou vazbu v komentářích.