Sprečavanje duplog submit-a forme
Jedan od standardnih problema kod prosleđivanja podatka sa forme je sprečavanje korisnika da slučajno ili namerno prosledi podatke dva ili više puta – dupli submit forme.
Podaci sa forme se mogu više puta proslediti višestrukim kikom na dugme za prosleđivanje forme, ili višestrukim učitavanjem stranice na koju je forma poslala podatke.
Tri načina za sprečavanje ovakvog ponašanja koja su ujedno i komplementarna su:
1.) Onemogućavanje višestrukog klika na dugme za prosleđivanje forme
Jednostavno ukinite dugme za slanje podataka nakon sto je prvi put pritisnuto na njega. Na taj način korisnik ne može slučajno da klikne više puta na “Submit”. Primer JavaScript koda koji bi mogao da se koristi:
<input type=”submit” onclick=”this.disabled=true” />
Mana ovog načina je što se izvršava na klijentskoj strani, i može biti nedovoljno sigurno. Takođe, forma se može poslati i klikom na enter u nekom od tekstualnih polja, čime se zaobilazi ovaj mehanizam provere.
Ovakva provera je sa druge strane dobra jer bezbolno rešava problem slučajnih višestrukih klikova, upravo zbog toga što radi na klijentskoj strani. Provere na strani servera su sigurnije, ali mnogo napornije za dobronamernog korisnika, jer zahtevaju od korisnika da se vrati nazad na formu i popuni podatke ponovo.
2.) Redirekcija (header) sa stranice za prihvatanje podataka sa forme nakon njihove obrade.
Ideja ovog načina je da se neposredno nakon obrađivanja podataka izvrši redirekcija na stranicu potvrde (koja može biti i ista stranica) sa ciljem da se korisnik spreči da prostim osvežavanjem stranice za obradu izvrši celu obradu ponovo.
Mana ovakve metode je što i daje ne sprečava korisnika da višestrukim klikom na dugme za slanje forme pozove stranicu za obradu više puta. Dodatni problem može da napravi slučaj kada se obrada sporo izvršava, u kom slučaju korisnik ipak može da osveži stranicu za obradu i izvrši je više puta.
Primer koda za redirekciju može da bude:
<?php
$posalji=$_POST[‘posalji’];
if($posalji){
//Izvrsi obradu
header(“Location: potvrdaObrade.php”);//Prosledi na stranicu potvrde
exit;//Obavezno nakon header-a da se spreci nastavak izvrsavanja stranice.
}else{
echo “Dosli ste ovde greskom!”;
}
?>
3.) Prosleđivanje ključa forme za proveru validnosti podataka
Ovom metodom sprečavate višestruku obradu podataka na serverskoj strani i ujedno sprečavate i pokušaje zlonamernih napada falsifikovanjem dolaznih podataka (Hijacking, DOS napad, Phishing i sl.).
Osnovna ideja je da se prilikom svakog prikaza forme za unos podataka dinamički kreira jedinstveni privremeni ključ koji se prosleđuje stranici za obradu podataka. Podaci se obrađuju samo ako se ključ verifikuje i upari sa polaznom formom, čime se obezbeđuje da se prihvataju samo podaci sa prvog submita forme i ujedno sprečava da se podaci falsifikuju (pod pretpostavkom da je algoritam generisanja kluča tajan).
Primer koda za ovu metodu može da bude:
//Stranica forma.php na kojoj je forma za unos podataka
<?php
session_start();
// algoritam za generisanje kljuca moze da bude bilo koji, ovo je jedan od mogucih
$_SESSION[‘kljucForme’] = md5(session_id() . time());
?>
<form action=”obrada.php” method=”post”>
<input type=”hidden” name=”kljuc” value=”<?php echo $_SESSION[‘kljucForme’] ?>” />
<input type=”text” name=”Ime” />
<input type=”submit” value=”Posalji” />
</form>
//Stranica obrada.php na kojoj je obrada poslatih podataka
<?php
session_start();
$originalniKljuc=$_SESSION[‘kljucForme’];//Pamcenje originalnog kljuca
unset($_SESSION[‘kljucForme’]);//Brisanje originalnog kljuca radi sprecavanja uparivanja dupliranih submita
$kljucForme=$_POST[‘kljuc’];//Pamcenje kljuca prosledjenog sa forme
if($kljucForme!=”” && $originalniKljuc==$kljucForme){//Dodatno proveravamo da $kljucForme nije prazan jer je to trivijlani slucaj koji je nedozvoljen
//Regularna Obrada
}else{
//Greska
}
?>
Ove tri metode najbolje rade u kombinaciji, jer svaka rešava određeni tip problema. Gornji primeri su ilustrativni, ono što je jako bitno je da uvek treba raditi ispravnu sanitizaciju ulaznih parametara (casting tipova i filtracija prosleđenih stringova od pokušaja XSS injectiona i SQL injectiona), što je preskočeno u gornjim primerima sa ciljem da oni budu što kraći i jasniji.
Ukoliko imate pitanja ili predloga, možete nas pratiti na @LimundoGradnja twitter nalogu.