Szablon programu broniącego się przed atakiem SQL Injection poprzez przygotowanie kodu SQL poleceniem prepare( „SQL” );

Wymaga nowego sposobu łączenia się z bazą danych. Kod obowiązkowy (do nauki na pamięć) ponieważ w większości przypadków aplikacji kopiuje się go zmieniając jedynie kod SQL, oraz kolumny tabeli wynikowej bind_result( kolumny) .

Typy bind_param:

  • s – string – napis (VARCHAR lub TEXT)
  • d – double – liczba rzeczywista
  • i – integer – liczba całkowita
  • b – blob – długi pakiet danych

marki.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
 <body>
  <table border="1">
   <?php
        if (!isset($_GET['marka']) || $_GET['marka']=="")
                die( "Blad: brak marki" ); // nie podano marki w formularzu
        $podaj_marke = $_GET['marka']; //pobieramy zmienna 'marka' z formularza
        include "polacz.php";
                              //przygotowanie kodu SQL:
        if ($sql = $baza->prepare( "SELECT marka,model FROM samochody WHERE marka LIKE ?"))
        {
                $sql->bind_param("s", $podaj_marke); //s - typu string, wklejamy w SQL w miejsce ? zmienna z formularza
                $sql->execute(); //wykonaj SQL
                $sql->bind_result($marka, $model);
                               // ^ wszystkie zmienne w tabeli wynikowej, po kolei, jak w SELECT marka,model ...
                while ($sql->fetch()) //czytanie tabeli wiersz po wierszu
                {      
                   echo "<tr>
                        <td>$marka</td>
                        <td>$model</td>
                      </tr>"
;
                }
                $sql->close();
        }
        $baza->close();
   ?>
  </table>
 </body>
</html>

polacz.php:

1
2
3
4
<?php
$baza = new  mysqli("localhost", "user", "haslo", "baza");
if (mysqli_connect_errno())  die( "Blad: ".mysqli_connect_error() );
?>

Formularz html:

1
2
3
4
5
6
7
8
<html>
 <body>
   <form action="marki.php" method="GET">
    Podaj marke: <input name="marka"><br>
    <input type="submit" value="OK">
   </form>
 </body>
</html>

PRZYKŁAD 2 (nie obowiązuje na pamięć)

Jeśli mamy więcej niż 1 zmienną z formularza, używamy dwóch znaków ?, a w prepare ciąg „ss” oznacza, że obie zmienne są typu string; Ale trzeba też sprawdzić, czy GET nie jest pusty, można sobie zdefiniować funkcję, która ułatwi nam życie i wpisać ją do polacz.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

function wczytaj($zmienna)
{
           if (!isset($_GET[$zmienna]) || $_GET[$zmienna]=="")
                die( "Blad! brak zmiennej: ".$zmienna ); // nie podano marki w $
           return $_GET[$zmienna];
}


$baza = new  mysqli("localhost", "user", "haslo", "baza");
if (mysqli_connect_errno())  die( "Blad: ".mysqli_connect_error() );
?>

wówczas uprości się główny program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
 <body>
  <table border="1">
   <?php
        include "polacz.php";
        $podaj_marke = wczytaj('marka'); //pobieramy zmienna 'marka' z formularza
        $podaj_model = wczytaj('model');
                              //przygotowanie kodu SQL:
        if ($sql = $baza->prepare( "SELECT marka,model FROM samochody WHERE marka LIKE ? OR model LIKE ?"))
        {
                $sql->bind_param("ss", $podaj_marke, $podaj_model); //s - typu string, mapujemy zmienna z formularza
                $sql->execute(); //wykonaj SQL
                $sql->bind_result($marka, $model);
                               // ^ wszystkie zmienne w tabeli wynikowej, po kolei, jak w SELECT marka,model ...
                while ($sql->fetch()) //czytanie tabeli wiersz po wierszu
                {
                   echo "<tr>
                        <td>$marka</td>
                        <td>$model</td>
                      </tr>"
;
                }
                $sql->close();
        }
        $baza->close();
   ?>
  </table>
 </body>
</html>

Działający przykład