PHP okénko: Unikátnost návštěvníka

Jakub Vrána 19. 5. 2006

Č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.

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:

IOT

<?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:

  1. Pokud je přítomna cookie, hlas nezapočíst.
  2. Pokud z této kombinace IP adresa + X-Forwarded-For bylo již tuto hodinu hlasováno, hlas nezapočíst.
  3. 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.

Ohodnoťte jako ve škole:

Průměrná známka 3,02

Našli jste v článku chybu?
Zasílat nově přidané názory e-mailem
120na80.cz: Superpotraviny. Jaké to jsou?

Superpotraviny. Jaké to jsou?

120na80.cz: Konopí: každá rostlina je jinak účinná

Konopí: každá rostlina je jinak účinná

Vitalia.cz: V Praze začne expozice vín a delikates

V Praze začne expozice vín a delikates

Měšec.cz: Státní hypotéky: Pro koho a za kolik?

Státní hypotéky: Pro koho a za kolik?

Podnikatel.cz: Nepřišlo vaše hlášení k DPH? Beřnák po vás jde

Nepřišlo vaše hlášení k DPH? Beřnák po vás jde

Podnikatel.cz: Cizinci v českém eshopu nechají miliardy

Cizinci v českém eshopu nechají miliardy

Podnikatel.cz: Podání u DPH ve špatném formátu? Je neúčinné

Podání u DPH ve špatném formátu? Je neúčinné

Root.cz: The Invisible Internet Project: konkurent Tor

The Invisible Internet Project: konkurent Tor

Podnikatel.cz: Když si reklamou "zabíjíte" zákazníky

Když si reklamou "zabíjíte" zákazníky

Vitalia.cz: Podmínky pro dárcovství kostní dřeně

Podmínky pro dárcovství kostní dřeně

Lupa.cz: Proč ve vlaku není signál? A který vagón je nejhorší?

Proč ve vlaku není signál? A který vagón je nejhorší?

Lupa.cz: Roaming se mění. Co byste o něm měli vědět?

Roaming se mění. Co byste o něm měli vědět?

Lupa.cz: V Brně vyvinuli rychlý internet do letadel

V Brně vyvinuli rychlý internet do letadel

Podnikatel.cz: Obchody zavřou během 3 svátků

Obchody zavřou během 3 svátků

Vitalia.cz: SZPI uzavřela Lidl. Takhle to tam vypadalo

SZPI uzavřela Lidl. Takhle to tam vypadalo

120na80.cz: Pánové, odřené bradavky při běhu nejsou nutné

Pánové, odřené bradavky při běhu nejsou nutné

Vitalia.cz: Očkování a autismus ve světle vědeckého objevu

Očkování a autismus ve světle vědeckého objevu

Lupa.cz: Jaký je Průvodce světem Arduina?

Jaký je Průvodce světem Arduina?

Podnikatel.cz: Nedodáte hlášení k DPH. Pokutu vám prominou

Nedodáte hlášení k DPH. Pokutu vám prominou

Podnikatel.cz: Google PageRank nadobro zmizel

Google PageRank nadobro zmizel

Ušetřete