Robisz tak dobrze, że naprawdę czuję się winny, gdy mówię, że robisz coś złego! :)
Do parametryzacji wartości pól można używać tylko przygotowanych instrukcji — nie można używać identyfikatorów SQL, takich jak nazwy kolumn lub tabel. Dlatego nie będziesz w stanie przekazać A.x
, B.z
itp. do swojego JOIN
kryteria za pomocą przygotowanych parametrów zestawienia:musisz zamiast tego zrób to, co wydaje się strasznie złe i bezpośrednio połącz je w łańcuch SQL.
Jednak, nie wszystko stracone. W pewnej niejasnej kolejności preferencji możesz:
-
Zaprezentuj użytkownikowi listę opcji, z której następnie ponownie asemblujesz SQL:
<select name="join_a"> <option value="1">x</option> <option value="2">y</option> </select> <select name="join_b"> <option value="1">z</option> <option value="2">y</option> </select>
Następnie Twój moduł obsługi formularza:
switch ($_POST['join_a']) { case 1: $acol = 'x'; break; case 2: $acol = 'y'; break; default: die('Invalid input'); } switch ($_POST['join_b']) { case 1: $bcol = 'z'; break; case 2: $bcol = 'y'; break; default: die('Invalid input'); } $sql .= "FROM A JOIN B ON A.$acol = B.$bcol";
Takie podejście ma tę zaletę, że poza narażaniem PHP (w takim przypadku będziesz miał znacznie większe obawy niż wstrzyknięcie SQL), arbitralny SQL absolutnie nie może znaleźć drogę do RDBMS.
-
Upewnij się, że dane wprowadzone przez użytkownika odpowiadają jednej z oczekiwanych wartości:
<select name="join_a"> <option>x</option> <option>y</option> </select> <select name="join_b"> <option>z</option> <option>y</option> </select>
Następnie Twój moduł obsługi formularza:
if (!in_array($_POST['join_a'], ['x', 'y']) or !in_array($_POST['join_b'], ['z', 'y'])) die('Invalid input'); $sql .= "FROM A JOIN B ON A.$_POST[join_a] = B.$_POST[join_b]";
To podejście opiera się na
in_array
PHP funkcja dla bezpieczeństwa (a także ujawnia użytkownikowi nazwy podstawowych kolumn, ale biorąc pod uwagę twoją aplikację, wątpię, czy jest to problem). -
Wykonaj pewne czyszczenie danych wejściowych, na przykład:
mb_regex_encoding($charset); // charset of database connection $sql .= 'FROM A JOIN B ON A.`' . mb_ereg_replace('`', '``', $_POST['join_a']) . '`' . ' = B.`' . mb_ereg_replace('`', '``', $_POST['join_b']) . '`'
Chociaż tutaj cytujemy dane wprowadzone przez użytkownika i zastępujemy wszelkie próby ucieczki od tego cytowania, to podejście może być pełne wszelkiego rodzaju wad i luk (w każdym
mb_ereg_replace
PHP funkcji lub obsługi przez MySQL specjalnie spreparowanych ciągów znaków w identyfikatorze w cudzysłowie).Jest daleko lepiej, jeśli to w ogóle możliwe, użyć jednej z powyższych metod, aby całkowicie uniknąć wstawiania ciągów zdefiniowanych przez użytkownika do własnego SQL.