PHP okénko: Unikátnost návštěvníka
Čas od času je potřeba zajistit, aby každý návštěvník mohl nějakou akci provést jenom jednou, např. hlasovat v anketě. Akci je možné podmínit registrací, která může být znepříjemněna pomocí CAPTCHA nebo kontroly e-mailové adresy. Pokud má návštěvník na e-maily doménový koš, tak si registrací může vytvořit libovolné množství, tento podvod lze ale obvykle snadno odhalit. Článek rozebírá možnosti, které máme, pokud od uživatele žádnou spolupráci vyžadovat nechceme.
Seriál PHP okénko
- PHP okénko: Kontrola e-mailové adresy
- PHP okénko: Unikátnost návštěvníka
- Filter a další novinky v PHP 5.2
- Webové služby v PHP: XML-RPC a SOAP
- Jmenné prostory a další novinky v PHP 5.3
V první řadě lze kontrolovat cookie:
<?php
if (isset($_COOKIE["hlasoval"])) {
echo "Váš hlas byl již dříve započten.\n";
} else {
setcookie("hlasoval", $_POST["hlas"], strtotime("+1 month"));
mysql_query("UPDATE anketa_odpovedi SET hlasy = hlasy + 1 WHERE id = '$_POST[hlas]'");
}
?>
Pokud má návštěvník cookies povolené, jedná se asi o nejspolehlivější způsob. Pokud si ale cookies zakáže, je tato kontrola k ničemu. V tom případě je možné kontrolovat ještě IP adresu. Ze dvou důvodů se nevyplatí spoléhat jenom na ni – jednak se adresa jednoho návštěvníka může v čase měnit (často je dynamicky přidělovaná) a jednak může jednu adresu používat víc lidí (při NAT zároveň, u dynamicky přidělovaných adres postupně). Doplňkové pravidlo je tedy vhodné nastavit např. tak, že z jedné IP adresy bude možné poslat pouze jeden hlas za hodinu:
<?php
if (isset($_COOKIE["hlasoval"])) {
echo "Váš hlas byl již dříve započten.\n";
} else {
setcookie("hlasoval", $_POST["hlas"], strtotime("+1 month"));
if (mysql_result(mysql_query("SELECT COUNT(*) FROM anketa_hlasy WHERE ip = '$_SERVER[REMOTE_ADDR]' AND datum + INTERVAL 1 HOUR > NOW()"), 0)) {
echo "Hlas z této adresy byl již dříve započten.\n";
} else {
mysql_query("INSERT INTO anketa_hlasy (hlas, ip, datum) VALUES ('$_POST[hlas]', '$_SERVER[REMOTE_ADDR]', NOW())");
}
}
?>
Pokud provoz prochází přes proxy server, bývá doplněna hlavička X-Forwarded-For a mohlo by nás to svádět, abychom ji kontrolovali. Protože jde ale tato hlavička snadno podvrhnout, nevyplatí se na ni spoléhat a je možné ji použít jen jako doplněk, např. takto:
- Pokud je přítomna cookie, hlas nezapočíst.
- Pokud z této kombinace IP adresa + X-Forwarded-For bylo již tuto hodinu hlasováno, hlas nezapočíst.
- Pokud již z této IP adresy v uplynulé hodině přišlo alespoň 5 hlasů, hlas nezapočíst.
<?php
if (isset($_COOKIE["hlasoval"])) {
echo "Váš hlas byl již dříve započten.\n";
} else {
setcookie("hlasoval", $_POST["hlas"], strtotime("+1 month"));
$forwarded_for = addslashes(preg_replace('~.*,\\s*~', '', $_SERVER["HTTP_X_FORWARDED_FOR"]));
if (mysql_result(mysql_query("SELECT COUNT(*) FROM anketa_hlasy WHERE ip = '$_SERVER[REMOTE_ADDR]' AND forwarded_for = '$forwarded_for' AND datum + INTERVAL 1 HOUR > NOW()"), 0)
|| mysql_result(mysql_query("SELECT COUNT(*) FROM anketa_hlasy WHERE ip = '$_SERVER[REMOTE_ADDR]' AND datum + INTERVAL 1 HOUR > NOW()"), 0) >= 5) {
echo "Hlas z této adresy byl již dříve započten.\n";
} else {
mysql_query("INSERT INTO anketa_hlasy (hlas, ip, forwarded_for, datum) VALUES ('$_POST[hlas]', '$_SERVER[REMOTE_ADDR]', '$forwarded_for', NOW())");
}
}
?>
Takto nastavená ochrana je již poměrně spolehlivá a v omezené míře je zranitelná pouze u lidí, kterým se mění IP adresa. U obvyklých kontrol jde ale hlavně o to možnost opakovaného provádění akce co nejvíc znepříjemnit. Pokud uživatel může s vyvinutím nemalého úsilí provést akci párkrát navíc, nejedná se o velký problém.
Školení: Django framework: Struktura a základy vývoje (nejen) webových aplikací
Django je vyspělý webový framework napsaný v jazyce Python, který podporuje extrémně rychlý vývoj společně s dodržováním principů dobrého návrhu. Snaží se co nejvíce automatizovat a drží se principu DRY (z anglického Don't Repeat Yourself — neopakuj se).
- Instalace potřebného softwaru
- Programování v Pythonu: příkazy, funkce, datové typy, moduly, objekty, výjimky
- Struktura aplikace v Djangu
- Typické záležitosti webových aplikací: Napojení na databázi, zpracování vstupu od uživatele, přihlášení či generování dynamického obsahu.
- Implementace principu MVC: modely, pohledy (views) a šablony
- Seznámení s užitečnými komponenty frameworku Django
- Šikovné praktiky
Podrobnější informace a přihláška
Seriál PHP okénko
- PHP okénko: Kontrola e-mailové adresy
- PHP okénko: Unikátnost návštěvníka
- Filter a další novinky v PHP 5.2
- Webové služby v PHP: XML-RPC a SOAP
- Jmenné prostory a další novinky v PHP 5.3
Přehled názorů
Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

