Nechtěný SQL insert při POST/GET.
Při programování vstupu do databáze a přidávání údajů do tabulky narazí každý na jev nežádoucího
přidání údajů do tabulky. Dochází k tomu třeba při osvěžení (refresh) obsahu stránky, obsahující
formulářové prvky. Pokud jsou údaje vložené do formulářových prvků předávány na webový server
pomocí metody POST, budeme vyzváni k opakování zaslání údajů, nebo odmítnutí zaslání, avšak při
použití metody GET budou údaje automaticky zopakovány, neboť veškeré předávané parametry se
nachází v příkazové řádce prohlížeče, připojeny k příslušnému URL.
Následující tabulka obsahuje čtyři naposledy vložené údaje. Údaje by měly být vloženy pouze při
stisknutí tlačítka 'Uložit'. Pokud toto tlačítko jednou stisknete, připojí se údaj z textového
pole jako poslední údaj k tabulce, což lehce zjistíme pozorováním čísla ve sloupci ID, které je
automaticky generováno SQL databází a je zaručeně jedinečné. Nadále již nepoužijeme tlačítko
'Uložit', ale obsah stránky osvěžíme, třeba přes nabídku vyvolanou pravým tlačítkem myši.
Zjistíme, že obsah textového pole bude opět přidán jako poslední řádek tabulky. To je ovšem
nežádoucí.
| ID | Text |
| 311 | Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'. |
| 312 | Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'. |
| 313 | Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'. |
| 314 | Podatak će biti pohranjen u tablici nakon pritisnuća tipke 'Spremiti'. |
Jak si sami můžete ověřit, pokud pro vložení údaje do tabulky použijete následující tlačítko
'Uložit', bude údaj do tabulky vložen pouze po jeho stisknutí a nikoliv při vyvolaném osvěžení
obsahu této stránky.
Dále bude uvedeno řešení, které zamezuje nechtěnému opakovanému vložení údajů do tabulky.
Popsáno bude s použitím skriptovacího jazyka PHP4, ovšem podobně lze problém řešit i s použitím
Javy, či jiných programovacích prostředků.
Jak bylo tohoto cíle dosaženo? Nejdříve byla vyhodnocena přítomnost proměnné, vyskytující se v
těle formuláře, nejlépe samotného tlačítka 'Uložit'. Protože veškeré proměnné jsou v podstatě
přítomny i při následném osvěžení obsahu stránky jako parametry v URL, je nutné je odstranit, zde
tak, že bezprostředně po uložení údajů do tabulky je webovému serveru zaslán opětovný požadavek
na tuto stránku, ovšem bez názvu a hodnoty proměnné, jejíž přítomnost vyhodnocujeme. Zde jsou
fragmenty zdrojového kódu v PHP4:
<?php // vyhodnocení přítomnosti proměnné z těla formuláře if (isset($save2)) { $udaj2 = addslashes(trim($udaj2)); $db->query("INSERT INTO manuals1 (txt) VALUES('$udaj2')"); // opětovaný požadavek na překreslení stránky bez parametrů header("Location: ../cz/cz_dbInsert.php"); } . . . <center> <table border="0" cellspacing="1" cellpadding="0"> <tr> <td class="tabid">ID</td> <td class="tabtxt">Text</td> </tr> <? $db->query("SELECT * FROM manuals1 ORDER BY Id"); while ($db->next_record()) { ?> <tr> <td class="tabid"><? echo $db->f("Id"); ?></td> <td class="tabtxt"><? echo stripslashes($db->f("txt")); ?></td> </tr> <? } ?> </table> <form method="GET" action="../cz/cz_dbInsert.php" target="body"> <!-- proměnná $save2 v těle formuláře --> <input type="submit" name="save2" value="Uložit" id="submit"> <input type="text" name="udaj2" value="Tento údaj .... tlačítka 'Uložit'."> </form> </center> ?>
Jak je zřejmé, ukládání údajů do tabulky předchází jejich vykreslení na stránce. Vhodné je
také umístit testování na přítomnost proměnné z těla formuláře na začátek skriptu, ještě před
samotné vykreslení stránky. Tím jistě zkrátíme potřebné časy a celý jev se nám bude zdát
jednolitý. Pozor ovšem na skutečnost, abychom při opětovném odeslání požadavku na server
vyloučili z předávaných parametrů název proměnné, kterou testujeme. V příkladu žádné parametry
nejsou v URL na server zasílány! Jinak pouze dosáhneme nekonrolovatelný počet opakovaného volání
serveru a tím i nedokončení činnosti skriptu, nehledě na přetížení webového serveru, prohlížeče
a sítě!
© 2005 Djordje Zurovac, všechna práva vyhrazena.