Ochrana ID relace v PHP. Úskalí používání relací v PHP Předávání hodnoty nebo pole pomocí relace PHP

Zdravím vás, milá komunito.

Nejprve vám chci poděkovat za velmi užitečný zdroj. Nejednou jsem zde našel mnoho zajímavých nápadů a praktických rad.

Účelem tohoto článku je upozornit na úskalí používání relací v PHP. Samozřejmostí je PHP dokumentace a spousta příkladů a tento článek nemá být úplným průvodcem. Je navržen tak, aby odhalil některé nuance práce s relacemi a ochránil vývojáře před zbytečným plýtváním časem.

Nejčastějším příkladem využití relací je samozřejmě autorizace uživatele. Začněme tou nejzákladnější implementací, abychom ji postupně rozvíjeli s novými úkoly.

(Abychom ušetřili prostor a čas, omezíme naše příklady pouze na samotné funkce relace, místo abychom zde budovali plnohodnotnou testovací aplikaci s krásnou hierarchií tříd, komplexním zpracováním chyb a dalšími dobrými věcmi).

Funkce startSession() ( // Pokud již byla relace spuštěna, zastavte provádění a vraťte TRUE // (parametr session.auto_start v souboru nastavení php.ini musí být zakázán - výchozí hodnota) if (session_id()) return true; else return session_start(); // Poznámka: Před verzí 5.3.0 vrátila funkce session_start() hodnotu TRUE, i když došlo k chybě. // Pokud používáte verzi starší než 5.3.0, proveďte další kontrolu for session_id() // po zavolání session_start() ) funkce cancelSession() ( if (session_id()) ( // Pokud existuje aktivní relace, odstraňte soubory cookie relace, setcookie(session_name(), session_id(), time( )-60*60*24); // a zničte relaci session_unset(); session_destroy(); ) )

Poznámka: Předpokládá se, že čtenář má základní znalosti PHP sessions, proto se zde nebudeme zabývat principem fungování funkcí session_start() a session_destroy(). Úlohy rozvržení přihlašovacího formuláře a autentizace uživatele s tématem článku nesouvisí, proto je také vynecháme. Dovolte mi jen připomenout, že pro identifikaci uživatele v každém dalším požadavku, v okamžiku úspěšného přihlášení, musíme identifikátor uživatele uložit do proměnné relace (například pojmenované userid), která bude k dispozici ve všech následujících požadavcích v rámci život relace. Je také nutné implementovat zpracování výsledku naší funkce startSession(). Pokud funkce vrátí hodnotu FALSE, zobrazte přihlašovací formulář v prohlížeči. Pokud funkce vrátila hodnotu TRUE a existuje proměnná relace obsahující identifikátor oprávněného uživatele (v našem případě - userid), zobrazte stránku oprávněného uživatele (více informací o zpracování chyb naleznete v dodatku ze dne 2013-06- 07 v části o proměnných relace).

Zatím je vše jasné. Otázky začínají, když potřebujete implementovat kontrolu nečinnosti uživatele (časový limit relace), umožnit více uživatelům pracovat současně v jednom prohlížeči a také chránit relace před neoprávněným použitím. O tom bude řeč níže.

Řízení nečinnosti uživatele pomocí vestavěných PHP nástrojů První otázkou, která často vyvstává mezi vývojáři různých konzolí pro uživatele, je automatické ukončení relace v případě nečinnosti ze strany uživatele. Není nic jednoduššího, než to udělat pomocí vestavěných schopností PHP. (Tato možnost není nijak zvlášť spolehlivá ani flexibilní, ale pro úplnost ji zvážíme).

Funkce startSession() ( // Časový limit nečinnosti uživatele (v sekundách) $sessionLifetime = 300; if (session_id()) vrátí true; // Nastaví životnost souboru cookie ini_set("session.cookie_lifetime", $sessionLifetime); // Pokud uživatel je nastaven časový limit nečinnosti, nastavte dobu trvání relace na serveru // Poznámka: Pro produkční server se doporučuje přednastavit tyto parametry v souboru php.ini if ​​($sessionLifetime) ini_set("session.gc_maxlifetime", $sessionLifetime) ; if (session_start( )) ( setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; ) else return false; )

Několik upřesnění. Jak víte, PHP určuje, kterou relaci je třeba spustit, podle názvu cookie odeslaného prohlížečem v hlavičce požadavku. Prohlížeč zase obdrží tento soubor cookie ze serveru, kam jej funkce session_start() umístí. Pokud vypršela platnost souboru cookie prohlížeče, nebude v požadavku odeslán, což znamená, že PHP nebude schopno určit, kterou relaci spustit, a bude to považovat za vytvoření nové relace. Parametr nastavení PHP session.gc_maxlifetime, který se rovná časovému limitu nečinnosti našeho uživatele, nastavuje dobu trvání relace PHP a je řízen serverem. Řízení doby trvání relace funguje následovně (zde považujeme příklad ukládání relací do dočasných souborů za nejběžnější a výchozí možnost v PHP).

Při vytvoření nové relace se vytvoří soubor s názvem sess_ v adresáři nastaveném jako adresář pro ukládání relací v parametru nastavení PHP session.save_path, kde je identifikátor relace. Dále, v každém požadavku, v době spuštění již existující relace, PHP aktualizuje čas úpravy tohoto souboru. V každém následujícím požadavku tak PHP může rozdílem mezi aktuálním časem a časem poslední úpravy souboru session určit, zda je session aktivní nebo její životnost již vypršela. (Mechanismus pro mazání starých souborů relace je podrobněji popsán v další části.)

Poznámka: Zde je třeba poznamenat, že parametr session.gc_maxlifetime platí pro všechny relace v rámci jednoho serveru (přesněji v rámci jednoho hlavního PHP procesu). V praxi to znamená, že pokud na serveru běží více webů a každý z nich má svůj časový limit nečinnosti uživatele, pak nastavení tohoto parametru na jednom z webů povede k jeho nastavení pro další weby. Totéž platí pro sdílený hosting. Aby se předešlo této situaci, používají se samostatné adresáře relací pro každou lokalitu na stejném serveru. Nastavení cesty k adresáři sessions se provádí pomocí parametru session.save_path v souboru nastavení php.ini nebo voláním funkce ini_set(). Poté budou relace každého webu uloženy v samostatných adresářích a parametr session.gc_maxlifetime nastavený na jednom z webů bude platný pouze pro jeho relaci. Tímto případem se nebudeme podrobně zabývat, zejména proto, že máme flexibilnější možnost sledování nečinnosti uživatelů.

Řízení nečinnosti uživatele pomocí proměnných relace Zdá se, že předchozí možnost přes veškerou svou jednoduchost (jen pár řádků kódu navíc) poskytuje vše, co potřebujeme. Ale co když ne každý požadavek lze považovat za výsledek aktivity uživatele? Stránka má například časovač, který pravidelně žádá AJAX o přijímání aktualizací ze serveru. Takový požadavek nelze považovat za aktivitu uživatele, což znamená, že automatické prodlužování doby trvání relace není v tomto případě správné. Ale víme, že PHP aktualizuje čas modifikace souboru session automaticky pokaždé, když je zavolána funkce session_start(), což znamená, že jakýkoli požadavek povede k prodloužení životnosti relace a nikdy nenastane časový limit nečinnosti uživatele. Navíc poslední poznámka z předchozí části o spletitosti parametru session.gc_maxlifetime se někomu může zdát příliš matoucí a obtížně implementovatelná.

Abychom tento problém vyřešili, opustíme používání vestavěných PHP mechanismů a zavedeme několik nových proměnných relace, které nám umožní sami řídit dobu nečinnosti uživatele.

Funkce startSession($isUserActivity=true) ($sessionLifetime = 300; if (session_id()) vrátí true; // Nastaví životnost cookie před zavřením prohlížeče (vše budeme kontrolovat na straně serveru) ini_set("session. cookie_lifetime", 0) ; if (! session_start()) vrátí hodnotu false; $t = time(); if ($sessionLifetime) ( // Pokud je nastaven časový limit nečinnosti uživatele, // kontrola času, který uplynul od poslední aktivity uživatele // (čas poslední žádosti, kdy byla aktualizována proměnná relace lastactivity) if (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // Pokud čas uplynul od poslední aktivita uživatele, / / ​​je větší než časový limit nečinnosti, což znamená, že relace vypršela a je třeba relaci ukončit zničitSession(); return false; ) else ( // Pokud časový limit ještě nenastal, // a pokud požadavek přišel v důsledku aktivity uživatele, // aktualizujte proměnnou lastactivity na hodnotu aktuálního jednoho času, // čímž prodloužíte dobu relace o další sekundy sessionLifetime if ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) vrátí true; )

Pojďme si to shrnout. V každém požadavku kontrolujeme, zda bylo dosaženo časového limitu od poslední aktivity uživatele do aktuálního okamžiku, a pokud bylo dosaženo, zničíme relaci a přerušíme provádění funkce s návratem FALSE. Pokud nebylo dosaženo časového limitu a funkci je předán parametr $isUserActivity s hodnotou TRUE, aktualizujeme čas poslední aktivity uživatele. Stačí ve volajícím skriptu určit, zda je požadavek výsledkem aktivity uživatele, a pokud ne, zavolat funkci startSession s parametrem $isUserActivity nastaveným na FALSE.

Doplněk ze 7. 6. 2013 Zpracování výsledku funkce sessionStart().

Komentáře poukázaly na to, že vrácení FALSE neposkytuje úplné pochopení příčiny chyby, a to je naprosto spravedlivé. Podrobné řešení chyb jsem zde nepublikoval (délka článku je již poměrně velká), jelikož to přímo nesouvisí s tématem článku. Ale vzhledem k komentářům to upřesním.

Jak vidíte, funkce sessionStart může ve dvou případech vrátit hodnotu FALSE. Buď relaci nebylo možné spustit kvůli některým interním chybám serveru (například nesprávné nastavení relace v php.ini), nebo vypršela životnost relace. V prvním případě musíme uživatele přesměrovat na stránku s chybou oznamující problémy na serveru a formulář pro kontaktování podpory. Ve druhém případě musíme uživatele převést do přihlašovacího formuláře a v něm zobrazit odpovídající zprávu o vypršení relace. K tomu musíme zadat chybové kódy a vrátit odpovídající kód místo FALSE a v metodě volání jej zkontrolovat a podle toho jednat.

Nyní, i když relace na serveru stále existuje, bude zničena při prvním přístupu, pokud vypršel časový limit nečinnosti uživatele. A to se stane bez ohledu na to, jaká životnost relace je nastavena v globálním nastavení PHP.

Poznámka: Co se stane, když byl prohlížeč zavřen a soubor cookie s názvem relace byl automaticky zničen? Požadavek na server při příštím otevření prohlížeče nebude obsahovat soubory cookie relace a server nebude moci otevřít relaci a zkontrolovat časový limit nečinnosti uživatele. Pro nás je to ekvivalentní vytvoření nové relace a žádným způsobem neovlivňuje funkčnost ani bezpečnost. Nabízí se ale férová otázka – kdo potom zničí starou relaci, když jsme ji až dosud zničili po vypršení časového limitu? Nebo bude nyní navždy viset v adresáři relací? Pro vyčištění starých relací v PHP existuje mechanismus zvaný garbage collection. Spustí se v době dalšího požadavku na server a vymaže všechny staré relace na základě data poslední úpravy souborů relace. Mechanismus garbage collection však nezačíná s každým požadavkem na server. Frekvenci (nebo spíše pravděpodobnost) spouštění určují dva parametry nastavení session.gc_probability a session.gc_divisor. Výsledkem dělení prvního parametru druhým je pravděpodobnost spuštění mechanismu garbage collection. Aby se tedy s každým požadavkem na server spustil mechanismus mazání relace, musí být tyto parametry nastaveny na stejné hodnoty, například „1“. Tento přístup zaručuje čistý adresář relace, ale je zjevně příliš drahý pro server. Na produkčních systémech je proto výchozí hodnota session.gc_divisor nastavena na 1000, což znamená, že mechanismus pro shromažďování odpadu poběží s pravděpodobností 1/1000. Pokud experimentujete s těmito nastaveními ve svém souboru php.ini, můžete si všimnout, že ve výše popsaném případě, když se prohlížeč zavře a vymaže všechny soubory cookie, v adresáři sessions na chvíli ještě zbývají staré relace. Ale to by vás nemělo znepokojovat, protože... jak již bylo řečeno, nemá to žádný vliv na bezpečnost našeho mechanismu.

Aktualizace ze 7. 6. 2013 Zabránění zamrznutí skriptů kvůli zamykání souboru relace

Komentáře vyvolaly problém zamrzání současně spuštěných skriptů kvůli zablokování souboru relace (nejvýraznější možností je dlouhé hlasování).

Nejprve poznamenávám, že tento problém přímo nezávisí na zatížení serveru nebo počtu uživatelů. Samozřejmě, čím více požadavků, tím pomaleji jsou skripty prováděny. Ale to je nepřímá závislost. Problém nastává pouze v rámci jedné relace, kdy server obdrží několik požadavků jménem jednoho uživatele (např. jeden z nich je dlouhé dotazování a zbytek jsou běžné požadavky). Každý požadavek se pokusí o přístup ke stejnému souboru relace, a pokud předchozí požadavek soubor neodemkl, následující požadavek přestane čekat.

Chcete-li udržet zamykání souboru relace na minimu, důrazně se doporučuje ukončit relaci voláním funkce session_write_close() ihned po dokončení všech akcí s proměnnými relace. V praxi to znamená, že byste neměli vše ukládat do proměnných relace a přistupovat k nim po celou dobu provádění skriptu. A pokud potřebujete uložit nějaká pracovní data do proměnných relace, přečtěte si je ihned po zahájení relace, uložte je do lokálních proměnných pro pozdější použití a zavřete relaci (to znamená ukončit relaci pomocí funkce session_write_close a nezničit ji pomocí session_destroy ).

V našem příkladu to znamená, že ihned po otevření relace, zkontrolování její životnosti a existence oprávněného uživatele, musíme přečíst a uložit všechny další proměnné relace požadované aplikací (pokud existují), poté relaci ukončit pomocí volání session_write_close() a pokračujte ve vykonávání skriptu, ať už je to dlouhé dotazování nebo běžný požadavek.

Ochrana relací před neoprávněným použitím Představme si situaci. Jeden z vašich uživatelů získá trojského koně, který okrádá soubory cookie prohlížeče (ve kterých je uložena naše relace) a odešle jej na zadaný e-mail. Útočník získá soubor cookie a použije jej ke zfalšování požadavku jménem našeho oprávněného uživatele. Server úspěšně přijme a zpracuje tento požadavek, jako by přišel od oprávněného uživatele. Pokud nebude implementováno dodatečné ověření IP adresy, povede takový útok k úspěšnému hacknutí uživatelského účtu se všemi z toho vyplývajícími důsledky.

Proč to bylo možné? Je zřejmé, že název a identifikátor relace jsou vždy stejné po celou dobu trvání relace, a pokud tato data obdržíte, můžete snadno odesílat požadavky jménem jiného uživatele (samozřejmě během trvání této relace). Nejedná se sice o nejběžnější typ útoku, ale teoreticky se jeví jako celkem proveditelný, zvláště vezmeme-li v úvahu, že takový trojský kůň nepotřebuje ani administrátorská práva k okradení cookies prohlížeče uživatele.

Jak se můžete chránit před útoky tohoto druhu? Opět samozřejmě omezením životnosti identifikátoru relace a periodickou změnou identifikátoru v rámci stejné relace. Můžeme také změnit název relace tak, že úplně smažeme starou a vytvoříme novou relaci, do ní zkopírujeme všechny proměnné relace ze staré. To ale neovlivňuje podstatu přístupu, takže se pro jednoduchost omezíme pouze na identifikátor relace.

Je jasné, že čím kratší je životnost ID relace, tím méně času bude mít útočník na získání a použití cookies k vytvoření uživatelského požadavku. V ideálním případě by měl být pro každý požadavek použit nový identifikátor, který minimalizuje možnost použití relace někoho jiného. Budeme však uvažovat obecný případ, kdy je doba regenerace identifikátoru relace nastavena libovolně.

(Vynecháme tu část kódu, která již byla probrána).

Funkce startSession($isUserActivity=true) ( ​​​​ // Doba trvání identifikátoru relace $idLifetime = 60; ... if ($idLifetime) ( // Pokud je nastavena doba trvání identifikátoru relace, // zkontrolujte dobu, která uplynula od relace vytvořeno nebo poslední regenerace // (čas posledního požadavku, kdy byla aktualizována proměnná relace starttime) if (isset($_SESSION["starttime"])) ( if ($t-$_SESSION["starttime"] >= $ idLifetime) ( // Čas vypršení životnosti identifikátoru relace // Vygenerování nového identifikátoru session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( // Dostaneme se sem, pokud relace právě skončila been created // Nastavte čas pro vygenerování identifikátoru relace na aktuální čas $_SESSION["starttime"] = $t; ) ) return true; )

Takže při vytváření nové relace (která nastane, když se uživatel úspěšně přihlásí) nastavíme proměnnou session starttime, která nám ukládá čas poslední generace identifikátoru relace, na hodnotu rovnou aktuálnímu času serveru. Dále v každém požadavku zkontrolujeme, zda od posledního vygenerování identifikátoru uplynul dostatek času (idLifetime), a pokud ano, vygenerujeme nový. Pokud tedy během nastavené životnosti identifikátoru útočník, který obdržel cookie oprávněného uživatele, nestihne jej použít, bude falešný požadavek serverem považován za neautorizovaný a útočník bude přesměrován na přihlašovací stránku. .

Poznámka: ID nové relace se dostane do cookie prohlížeče, když je zavolána funkce session_regenerate_id(), která odešle nový cookie, podobně jako funkce session_start(), takže nemusíme sami aktualizovat cookie.

Pokud chceme, aby naše relace byly co nejbezpečnější, stačí nastavit životnost identifikátoru na jedničku nebo dokonce odstranit funkci session_regenerate_id() ze závorek a odstranit všechny kontroly, což povede k regeneraci identifikátoru v každé žádost. (Netestoval jsem dopad tohoto přístupu na výkon a mohu pouze říci, že funkce session_regenerate_id(true) v podstatě provádí pouze 4 akce: vygenerování nového identifikátoru, vytvoření hlavičky s cookie relace, smazání starého a vytvoření nový soubor relace).

Lyrická odbočka: Pokud se trojský kůň ukáže být natolik chytrý, že neposílá útočníkovi cookies, ale zorganizuje odeslání předem připraveného falešného požadavku ihned po obdržení cookie, výše popsaná metoda s největší pravděpodobností nebude schopna chránit před takovým útokem, protože mezi okamžikem, kdy trojský kůň obdrží cookie, a odesláním falešného požadavku nebude prakticky žádný rozdíl a je vysoká pravděpodobnost, že v tuto chvíli nebude identifikátor relace vygenerován.

Možnost současné práce v jednom prohlížeči jménem více uživatelů Posledním úkolem, který bych rád zvážil, je možnost současné práce více uživatelů v jednom prohlížeči. Tato funkce je užitečná zejména ve fázi testování, kdy potřebujete simulovat současnou práci uživatelů, a je vhodné to udělat ve vašem oblíbeném prohlížeči, spíše než používat celý dostupný arzenál nebo otevírat několik instancí prohlížeče v režimu inkognito .

V našich předchozích příkladech jsme výslovně nespecifikovali název relace, takže byl použit výchozí název PHP (PHPSESSID). To znamená, že všechny relace, které jsme dosud vytvořili, odeslaly do prohlížeče cookie pod názvem PHPSESSID. Je zřejmé, že pokud je název souboru cookie vždy stejný, neexistuje způsob, jak uspořádat dvě relace se stejným názvem ve stejném prohlížeči. Pokud bychom ale pro každého uživatele použili vlastní název relace, problém by byl vyřešen. Pojďme to udělat.

Funkce startSession($isUserActivity=true, $prefix=null) ( ... if (session_id()) vrátí true; // Pokud je předpona uživatele předána v parametrech, // nastavte jedinečný název relace, který toto zahrnuje prefix, // jinak nastavit společný název pro všechny uživatele (například MYPROJECT) session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) vrátí false; ... )

Nyní zbývá pouze zajistit, aby volající skript předal funkci startSession() jedinečnou předponu pro každého uživatele. To lze provést například předáním prefixu v parametrech GET/POST každého požadavku nebo prostřednictvím dodatečného cookie.

Závěr Na závěr uvedu kompletní finální kód našich funkcí pro práci s PHP sessions, včetně všech výše diskutovaných úloh.

Funkce startSession($isUserActivity=true, $prefix=null) ( $sessionLifetime = 300; $idLifetime = 60; if (session_id()) vrátí true; session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) vrátí hodnotu false; $t = time(); if ($sessionLifetime) ( if (isset($_SESSION["lastactivity"] ) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( cancelSession(); return false; ) else ( if ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) if ($idLifetime ) ( if (isset($_SESSION["starttime"])) ( if ($t-$_SESSION["starttime"] >= $idLifetime) ( session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( $_SESSION["starttime"] = $t; ) ) vrátí true; ) funkce cancelSession() ( if (session_id()) ( session_unset(); setcookie(session_name(), session_id(), time() -60*60*24); session_destroy(); ) )

Doufám, že tento článek ušetří čas těm, kteří se do mechanismu relace nikdy neponořili příliš hluboko, a poskytne dostatek informací o tomto mechanismu těm, kteří se s PHP teprve začínají seznamovat.

Potřebujete uživatelské jméno a heslo?

Chcete-li odesílat články online a kontrolovat stav odeslaných článků, musíte se zaregistrovat a přihlásit se ke svému účtu.

Kontrolní seznam pro přípravu článku k odeslání

V rámci procesu odesílání článku musí autoři zkontrolovat, zda jejich článek splňuje všechny následující body; články mohou být vráceny autorům, pokud tyto požadavky nesplňují.

Článek byl zpracován v souladu s požadavky

Podmínky převodu autorských práv

Autoři si ponechávají autorská práva k dílu a udělují časopisu práva na první publikaci spolu s dílem, přičemž jej licencují za podmínek licence Creative Commons Attribution License, která umožňuje ostatním distribuovat toto dílo s povinným uvedením autora díla a odkazem k původní publikaci v tomto časopise.

Prohlášení o ochraně soukromí

Jména a e-mailové adresy zadané na webových stránkách tohoto časopisu budou použity výhradně pro účely určené tímto časopisem a nebudou použity k žádnému jinému účelu ani poskytnuty žádné jiné osobě nebo subjektu.

Před registrací do systému uživatel souhlasí se zásadami zpracování a uchovávání osobních údajů.

Autorské platby

1500 znaků s mezerami: 300,00 (RUB)

Publikace 1 strany rukopisu (1500 znaků) - 300 rublů. Grafické materiály / tabulky se platí zvlášť - 50 rublů / 1 kus. Autorská kopie včetně dopravy v rámci Ruska se platí na žádost autora - 400 rublů. Doprava do zahraničí - 800 rublů. Náklady na zaslání potvrzení o přijetí materiálu k publikaci jsou 150 rublů.

Překlad doprovodných informací (celé jméno, místo práce autorů; název; abstrakt; klíčová slova) do angličtiny 0,5 rublů za každý znak včetně mezer.

Pozornost! Autoři (kandidáti a doktoři věd), kteří mají podle elibrary.ru 300 a více citací (podíl autocitací by neměl být vyšší než 30 %), jsou publikováni zdarma. Pokud máte nárok na bezplatnou publikaci, uveďte při odesílání materiálu do pole pro komentáře odkaz na svůj profil knihovny s počtem citací. Poštovné za odběr se platí zvlášť.

Zabezpečení webu je založeno na správě relací. Když se uživatel připojí k zabezpečenému webu, poskytne přihlašovací údaje, obvykle ve formě uživatelského jména a hesla. Webový server netuší, který uživatel je již přihlášen nebo jak se pohybuje ze stránky na stránku. Mechanismus relace zabraňuje uživatelům, aby museli zadávat heslo pokaždé, když chtějí provést novou akci nebo přejít na novou stránku.

Správa relací v podstatě zajišťuje, že aktuálně připojený uživatel je ten, kdo byl ověřen. Ale bohužel se relace staly zřejmým cílem pro hackery, protože mohou umožnit přístup k webovému serveru bez nutnosti autentizace.

Po ověření uživatele mu webový server poskytne ID relace. Toto ID je uloženo v prohlížeči a je nahrazeno vždy, když je potřeba ověření. To vám umožní vyhnout se opakovaným procesům přihlašování/zadávání hesla. To vše se děje na pozadí a nezpůsobuje uživateli nepohodlí. Představte si, že byste zadávali své uživatelské jméno a heslo pokaždé, když jste si prohlíželi novou stránku!

V tomto článku se pokusím nastínit všechny způsoby, které znám, jak chránit ID relace v PHP.

Používání souborů cookie Ve výchozím nastavení jsou všechny informace o relaci, včetně ID, odesílány do souboru cookie. Ale to se nestává vždy. Někteří uživatelé zakazují soubory cookie ve svých prohlížečích. V tomto případě prohlížeč předá ID relace v adrese URL.

Zde je ID přenášeno jako prostý text, na rozdíl od relace přes cookie, když je informace skryta v HTTP hlavičce. Nejjednodušší způsob, jak se proti tomu chránit, by bylo zakázat přenos identifikátoru relace přes adresní řádek. To lze provést zapsáním následujícího do konfiguračního souboru .htaccess serveru Apache:

Php_flag session.use_only_cookies zapnuté

Použití šifrování Pokud váš web musí zpracovávat citlivé informace, jako jsou čísla kreditních karet (zdravíme vás od Sony), měli byste použít šifrování SSL3.0 nebo TSL1.0. Chcete-li to provést, musíte při nastavování souboru cookie zadat hodnotu true pro parametr secure.

Pokud ukládáte heslo relace do proměnné $_SESSION (stále je lepší použít sql), neměli byste ho ukládat jako prostý text.

If ($_SESSION["heslo"] == $userpass) ( // kód )

Výše uvedený kód není bezpečný, protože heslo je uloženo jako prostý text v proměnné relace. Místo toho použijte šifrování md5, něco takového:

If ($_SESSION["md5password"] == md5($userpass)) ( // kód )

Kontrola prohlížeče Chcete-li zabránit možnosti použití relace z jiného prohlížeče (počítače), měli byste zadat kontrolu pole záhlaví HTTP user-agent:

Session_start(); if (isset($_SESSION["HTTP_USER_AGENT"])) ( if ($_SESSION["HTTP_USER_AGENT"] != md5($_SERVER["HTTP_USER_AGENT"])) ( // kód ) ) else ( $_SESSION["HTTP_USER_AGENT" ] = md5($_SERVER["HTTP_USER_AGENT"]); )

Vypršení platnosti relace Omezte dobu trvání relace a také dobu vypršení platnosti souborů cookie. Ve výchozím nastavení je délka relace 1440 sekund. Tuto hodnotu můžete změnit prostřednictvím php.ini a .htaccess. Příklad pro .htaccess:

# Životnost relace v sekundách
php_value session.gc_maxlifetime 3600
# Životnost cookie v sekundách
php_value session.cookie_lifetime 3600

Vazba podle adresy IP V určitých situacích (ne vždy) byste se měli vázat pomocí adresy IP. Hlavně když je omezený počet uživatelů a mají statické IP. Kontrola může být buď na základě seznamu povolených IP adres,

Include("ip_list.php"); //$ip_white_list = pole ("admin1" => "111.222.333.444", "admin2" => "555.666.777.888"); if(!empty(array_search($_SERVER["REMOTE_ADDR"],$ip_white_list))) ( header("Location: admin.php"); ) else ( echo "PŘÍSTUP ZAMÍTNUT!"; )

Nebo podle IP adresy pro každý požadavek (pouze pro statickou IP):

If(isset($_SESSION["ip"]) a $_SESSION["ip"] == $_SERVER["REMOTE_ADDR"]) ( header("Location: admin.php"); ) else ( session_unset(); $ _SESSION["ip"] = $_SERVER["REMOTE_ADDR"]; )

Měli byste si být vědomi toho, že hackování se nelze úplně vyhnout. Tento hack můžete jen co nejvíce ztížit jakýmkoli známým způsobem. Zapomínat byste však neměli ani na své legální uživatele, abyste jim takovou ochranou nekomplikovali život.

Tento článek byl napsán v roce 2009 a zůstává jedním z našich nejoblíbenějších příspěvků. Pokud se chcete dozvědět více o PHP a MySQL, možná vás to bude velmi zajímat.

POZNÁMKA: Tento článek byl nově aktualizován, aby fungoval na PHP 4.2 nebo novějším!

Nedávno jsem měl příležitost pracovat na malém projektu se skupinou lidí. Již na začátku jsme se rozhodli, že samotný e-mail nebude stačit k tomu, aby byli všichni v obraze, takže jsem dostal za úkol vytvořit pro projekt malou webovou stránku. Obsahoval by jednoduchou nástěnku, místo, kam bychom mohli nahrávat dokumenty a další soubory pro použití zbytku týmu, a kontaktní informace na různé členy týmu.

Aby mnoho z těchto funkcí fungovalo, věděl jsem, že potřebuji, aby se uživatelé před přístupem k relevantním částem webu přihlásili. Potřeboval jsem systém, který by uživatelům umožnil zaregistrovat se k uživatelskému ID pro přístup na stránku a poté toto ID okamžitě použít bez jakéhokoli zásahu z mé strany.

V tomto článku poskytnu přehled systému, který jsem vyvinul, počínaje první polovinou procesu registrace uživatele. Ve druhé polovině se zaměřím na samotný web, na to, jak vyžaduje přihlášení uživatelů, a poté tento stav přihlášení udržuje po celou dobu jejich návštěvy. Zvláštní pozornost budu věnovat použití funkcí správy relací v PHP. Nakonec byste měli mít všechny informace, které potřebujete k implementaci podobného vlastního systému.

V celém tomto článku budu předpokládat, že máte základní znalosti jazyka PHP, používání formulářů pro odesílání informací do skriptu PHP a toho, jak lze PHP použít k interakci s databází MySQL. Pokud jsou pro vás některé z těchto pojmů cizí pojmy, měli byste začít přečtením mého předchozího článku, .

Část první: Proces registrace Registrační formulář

Přirozeným místem, kde začít s budováním webu, který bude vyžadovat registraci uživatelů pro přístup, je samotný registrační proces. Jak by se dalo očekávat, jednoduchý webový formulář bude stačit. Bude to vypadat následovně:

A zde je kód pro tento formulář:




Registrace nového uživatele



Registrační formulář nového uživatele

* označuje povinné pole


Když je cíl nyní jasný, provedu vás kódem pro accesscontrol.php . Začněte tím, že přidáte své dva užitečné soubory include: