Kontrola vícenásobného přístupu - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



PHP

Kontrola vícenásobného přístupu

php_ipcheck

28. března 2001, 00.00 | Potřebujete zamezit vícenásobnému použití vašeho skriptu, např. vícenásobnému hlasování? Poradíme vám jak na to. Článek obsahuje řadu praktických ukázek a osvědčených postupů!

V několika minulých článcích jsme byli postaveni před otázku, jak zabezpečit vícenásobné použití daného skriptu. Za všechny vyberu ten nejznámější, a to anketní systém - hlasování. Zde je potřebné, aby uživatel nemohl hlasovat vícekrát a znehodnotit tak smysl celého hlasování.

Nastíníme si několik přístupů:

1. Naivní
Méně zkušeného programátora jistě napadne použití cookies. Tato technologie je poměrně dobře implementovatelná a má velmi dobrou podporu v programovacích jazycích (PHP, JS).
Je ale třeba si uvědomit, že cookies si uživatel může vypnout. Tj. ochrana se stává neúčinnou. Lze namítnout, že procento uživatelů používajích cookies je dnes poměrně velké a proto můžeme navrhnout systém využívající pouze cookies (tj. uživatele bez podpory cookies vyloučit). To je ale velmi neštastné řešení, jelikož cookies lze velmi lehce modifikovat!

Rada závěrem: v tomto případě lze využít cokies, ale pouze jako podpůrný prostředek. Např. lze do ní uložit informaci, zda uživatel již hlasoval. V případě, že cookies neexistuje, je třeba aplikovat nějaký sofistikovanější kontrolní mechanizmus.

2. Jeden SQL dotaz
Pokud chceme uživateli zabránit v opakovaném úkonu, je třeba ho nejdříve identifikovat. Nám k tomuto účelu poslouží IP adresa uživatele (lze samozřejmě vybrat jiný údaj, či kombinaci údajů).
Tím ovšem nastává problém přesnosti identifikace. Je všeobecně známo, že pod jednou IP adresou se může nacházet více reálných uživatelů (v tomto ohledu mají cookies jasnou výhodu, identifikují přímo uživatele). S tím je nutno počítat, činnost jednoho uživatele z dané IP adresy nesmí diskriminovat ostatní uživatele s touto adresou (příkladem jsou vysoké školy, často schované za cache ap. Pokud bychom toto neošetřili, hlas jednoho studenta by znemožnil hlasovat stovkám dalších!).
Dalším požadavkem je rychlost. Kontrola uživatele nesmí trvat příliž dlouho. Čím méně, tím lépe.

Optimální je zapracovat kontrolu přímo do SQL dotazu. Např. u hlasování je to UPDATE, kdy zvyšujeme jeden ze sloupců:

UPDATE tabulka SET vote=vote+1, last_ip='$IP', last_vote='$now' 
WHERE uid='$uid' AND (last_ip<>'$IP' OR last_vote + $delay < $now)


Toto je velmi primitivní kontrola, kdy kontrolujeme, zda nedochází k opakovanému hlasování.
Vysvětlení pojmů:

  • vote - sloupec, ke kterému bráníme vícenásobný přístup.
  • $IP - IP adresa uživatele.
  • last_ip - IP adresa naposledy hlasujícího uživatele.
  • last_vote - Čas posledního hlasování (jako unix_timestamp).
  • $now - Aktuální čas.
  • $delay - časový interval [sekundy], kdy uživatel se stejným IP nesmí hlasovat.

Pokud je $delay nastaven např. na 60, znamená to že uživatel z jedné IP adresy nemůže dvakrát po sobě hlasovat po dobu 1 minuty. Pokud zahlasuje po tomto intervalu, je hlas uznán. Rovněž je hlas uznán, pokud v tomto intervalu zahlasuje někdo jiný - přemaže se informace last_ip.

To lze odstranit sledováním více IP adres:

UPDATE tabulka SET vote=vote+1, last_ip2=last_ip1, last_ip1=last_ip, 
 last_ip='$IP', last_vote='$now' WHERE uid='$uid' 
 AND ((last_ip<>'$IP' AND last_ip1<>'$IP' AND last_ip2<>'$IP') 
 OR last_vote + $delay < $now)

Princip je stejný jako v předcházejícím případě, pouze jsou kontrolovány tři poslední IP. Počet takto kontrolovaných adres lze nastavit dle předpokládané zátěže (počtu přístupů uživatelů), ovšem více než pět bych nedoporučoval - příliž velká zátěž, lze řešit lépe. Viz následující bod.

3. Kontrola četnosti
V předcházejícím bodě jsme si ukázali, jak efektivně kontrolovat násobný přístup na úrovni jednoho záznamu. Výhodou byla rychlost a snadnost provedení, nevýhodou pak omezený počet sledovaných záznamů. Další nevýhodou předcházející metody je striktní omezení na jeden přístup. Nelze definovat, aby uživatel mohl přistoupit např. maximálně třikrát za pět minut.
Uvedené nevýhody odstraníme metodou nazvanou "Kontrola četnosti".
Bohužel již na počátku se musíme vzdát snadnosti realizace minulého bodu. Již nelze přidat kontrolu do stávající tabulky. Musíme vytvořit tabulku novou.
Ta bude obsahovat tyto údaje:
Tabulka Ipcheck

  • uid - int - pomocný údaj pro lepší manipulaci s daty.
  • ip - char(16) - IP adresa uživatele.
  • last - datetime - Poslední přístup uživatele z danné IP adresy.
  • number - int(11) - Celkový počet přístupů z této adresy.

Kandidátem na primární klíč je položka ip, nicméně si nejsem jistý, zda je vhodné primární klíč (resp. index) definovat. Tabulku často promazáváme, data jsou relativně často vkládána a ne tak často čtena. Zřejmě záleží na použitém typu úlohy a db stroji.

Samotný algoritmus je popsán funkcí ipcheck v PHP v rámečku níže. Fukce vrací nenulovou hodnotu, je-li uživatel v pořádku a nulovou pokud přistupuje vícekrát, než jsme dovolili.
Dále jsou definovány tyto vstupní proměnné:

  • $ip_min - v jakém časovém intervalu provádíme kontrolu na četnost [minuty].
  • $ip_max - kolikrát v tomto intervalu může uživatel přijít.


Funkce se chová následovně:

  • Nemá-li uživatel záznam, vrať OK. Nastav záznam uživatele (IP, čas příchodu).
  • Existuje-li záznam, zjisti čas poslední návštevy:
    • Uživatel zde byl naposledy před delší dobou než je $ip_min - Vrať OK, oprav záznam uživatele (nastav number na nulu a čas na aktuální).
    • Uživatel zde byl naposledy před kratší dobou než je $ip_min - Zkontroluj údaj number:
      • Menší než $ip_max - Vrať OK,oprav záznam uživatele (zvyš number o jedničku, čas na aktuální).
      • Větší než $ip_max - Vrať ŠPATNĚ, oprav záznam uživatele (čas na aktuální).
/* konfigurace */
$ip_min=1; //kolik minut
$ip_max=8; //kolikrat muze prijit


function ipcheck()
{
global $REMOTE_ADDR, $ip_min, $ip_max;

$ip=$REMOTE_ADDR;

$q="SELECT uid, DATE_SUB(now(), INTERVAL $ip_min MINUTE) < last , number 
FROM ipcheck WHERE ip='$ip'";
$r=mysql_query($q) or die(mysql_error());
$n=mysql_numrows($r);

if(!$n) {
	/* ip jeste nemame */
	$q="INSERT INTO ipcheck (ip, last, number) VALUES('$ip',now(),0)";
	mysql_query($q) or die(mysql_error());
	return 1;
	}

/* ip uz tam je.. */
$uid=mysql_result($r,0,0);
	
if(mysql_result($r,0,1))
	{
	/* ten clovek tu je za posledni minutu uz ponekolikate.. */
	$prist=mysql_result($r,0,2);
	$prist++;
	$q="UPDATE ipcheck SET last=now(), number=$prist WHERE uid='$uid'";
	mysql_query($q) or die(mysql_error());
	if($prist<$ip_max) {
		/* je to ok */
		return 1;
		}	
		else
		{
		/* je to spatny */
		return 0;	
		}
	}
/* ten clovek ma sice zaznam, ale uz tu dlouho nebyl */
$q="UPDATE ipcheck SET last=now(), number=1 WHERE uid='$uid'";
mysql_query($q) or die(mysql_error());
return 1;
}


Několik poznámek:

  • Kvůli přílišnému nárůstu dat je vhodné tabulku periodicky promazávat. Tj. smazat záznamy, které jsou starší než $ip_min.
  • Díky vhodně volenému prvnímu SQL dotazu jsme získali kontrolu přístupu na pouhé dva SQL dotazy. Jedná se sice o operačně složitější řešení než v druhém případě, ovšem je určeno pro jinou doménu problémů. (první metoda = anketní systémy, tato metoda = reklamní systémy ap.)
  • Tato metoda se nehodí pro kontrolu např. hlasování. Na rozdíl od předcházející totiž zamezí hlasování i u anket s jiným uid. Jedná se o globální kontrolu (zatímco předcházející metoda dělá kontrolu na úrovni záznamu).

Tématické zařazení:

 » Rubriky  » PHP  

 » Rubriky  » Web  

Diskuse k článku

 

Vložit nový příspěvek   Sbalit příspěvky

 

Zatím nebyl uložen žádný příspěvek, buďte první.

 

 

Vložit nový příspěvek

Jméno:

Pohlaví:

,

E-mail:

Předmět:

Příspěvek:

 

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: