PHP + MySQL, jak se bezpečně spojit a fungovat.

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:

  1. pro demonstrační účely nastavuji proměnnou, kterou využiji v dotazu
  2. 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
  3. 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.

One Response to PHP + MySQL, jak se bezpečně spojit a fungovat.