Zaštita ID-a sesije u PHP-u. Zamke korišćenja sesija u PHP-u Prenošenje vrednosti ili niza pomoću PHP sesije

Pozdrav, draga zajednica.

Prije svega, želim da vam se zahvalim na veoma korisnom resursu. Više puta sam ovdje pronašao mnogo zanimljivih ideja i praktičnih savjeta.

Svrha ovog članka je da istakne zamke korištenja sesija u PHP-u. Naravno, postoji PHP dokumentacija i mnoštvo primjera, a ovaj članak nema namjeru da bude potpuni vodič. Dizajniran je da otkrije neke od nijansi rada sa sesijama i zaštiti programere od nepotrebnog gubljenja vremena.

Najčešći primjer korištenja sesija je, naravno, autorizacija korisnika. Počnimo s najosnovnijom implementacijom kako bismo je postepeno razvijali kako se pojavljuju novi zadaci.

(Da bismo uštedjeli prostor i vrijeme, ograničit ćemo naše primjere samo na same funkcije sesije, umjesto da ovdje gradimo punopravnu testnu aplikaciju sa prekrasnom hijerarhijom klasa, sveobuhvatnim rukovanjem greškama i drugim dobrim stvarima).

Funkcija startSession() ( // Ako je sesija već pokrenuta, zaustavite izvršavanje i vratite TRUE // (parametar session.auto_start u datoteci postavki php.ini mora biti onemogućen - zadana vrijednost) ako (session_id()) vrati true; inače vraća session_start(); // Napomena: Prije verzije 5.3.0, funkcija session_start() je vraćala TRUE čak i ako je došlo do greške. // Ako koristite verziju stariju od 5.3.0, izvršite dodatnu provjeru for session_id() // nakon poziva session_start() ) funkcija destroySession() ( if (session_id()) ( // Ako postoji aktivna sesija, obrišite kolačiće sesije, setcookie(session_name(), session_id(), time( )-60*60*24); // i uništimo sesiju session_unset(); session_destroy(); ) )

Napomena: Pretpostavlja se da čitalac ima osnovno znanje o PHP sesijama, tako da ovde nećemo pokrivati ​​princip rada session_start() i session_destroy() funkcija. Zadaci izgleda obrasca za prijavu i autentifikacije korisnika nisu vezani za temu članka, pa ćemo ih također izostaviti. Samo da vas podsjetim da za identifikaciju korisnika u svakom sljedećem zahtjevu, u trenutku uspješne prijave, moramo pohraniti identifikator korisnika u varijablu sesije (nazvanu userid, na primjer), koja će biti dostupna u svim narednim zahtjevima unutar život sesije. Također je potrebno implementirati obradu rezultata naše startSession() funkcije. Ako funkcija vrati FALSE, prikažite obrazac za prijavu u pretraživaču. Ako je funkcija vratila TRUE, a varijabla sesije koja sadrži identifikator ovlaštenog korisnika (u našem slučaju - userid), postoji - prikažite stranicu ovlaštenog korisnika (za više informacija o rukovanju greškama pogledajte dodatak od 2013-06- 07 u odjeljku o varijablama sesije).

Za sada je sve jasno. Pitanja počinju kada trebate implementirati kontrolu neaktivnosti korisnika (vremensko ograničenje sesije), omogućiti više korisnika da rade istovremeno u jednom pretraživaču, a također zaštititi sesije od neovlaštenog korištenja. O tome će biti riječi u nastavku.

Kontrola neaktivnosti korisnika pomoću ugrađenih PHP alata Prvo pitanje koje se često postavlja među programerima raznih konzola za korisnike je automatski prekid sesije u slučaju neaktivnosti od strane korisnika. Ne postoji ništa lakše nego to učiniti koristeći ugrađene mogućnosti PHP-a. (Ova opcija nije posebno pouzdana ili fleksibilna, ali ćemo je razmotriti radi potpunosti).

Funkcija startSession() ( // Vremensko ograničenje neaktivnosti korisnika (u sekundama) $sessionLifetime = 300; if (session_id()) vrati true; // Postavi životni vijek kolačića ini_set("session.cookie_lifetime", $sessionLifetime); // Ako korisnik vremensko ograničenje neaktivnosti je postavljeno, podesite životni vek sesije na serveru // Napomena: Za proizvodni server, preporučuje se da unapred postavite ove parametre u php.ini fajl if ($sessionLifetime) ini_set("session.gc_maxlifetime", $sessionLifetime) ; if (session_start()) (setcookie(session_name(), session_id(), time()+$sessionLifetime); vrati true; ) else vrati false; )

Nekoliko pojašnjenja. Kao što znate, PHP određuje koja sesija treba da se pokrene prema imenu kolačića koji pretraživač šalje u zaglavlju zahteva. Pregledač, zauzvrat, prima ovaj kolačić od servera, gdje ga funkcija session_start() postavlja. Ako je kolačić pretraživača istekao, neće biti poslan u zahtjevu, što znači da PHP neće moći odrediti koju sesiju da pokrene i tretirat će to kao stvaranje nove sesije. Parametar postavki PHP-a session.gc_maxlifetime, koji je postavljen kao vremensko ograničenje neaktivnosti korisnika, postavlja životni vijek PHP sesije i kontrolira ga server. Kontrola životnog veka sesije funkcioniše na sledeći način (ovde razmatramo primer čuvanja sesija u privremenim datotekama kao najčešću i podrazumevanu opciju u PHP-u).

Kada se kreira nova sesija, kreira se datoteka pod nazivom sess_ u direktoriju postavljenom kao direktorij za pohranjivanje sesija u parametru PHP postavki session.save_path, gdje je identifikator sesije. Zatim, u svakom zahtjevu, u trenutku pokretanja već postojeće sesije, PHP ažurira vrijeme modifikacije ove datoteke. Dakle, u svakom sledećem zahtevu, PHP, na osnovu razlike između trenutnog vremena i vremena poslednje izmene fajla sesije, može odrediti da li je sesija aktivna ili je njen životni vek već istekao. (Mehanizam za brisanje starih datoteka sesije je detaljnije razmotren u sljedećem odjeljku.)

Napomena: Ovdje treba napomenuti da se parametar session.gc_maxlifetime primjenjuje na sve sesije unutar jednog servera (tačnije, unutar jednog glavnog PHP procesa). U praksi, to znači da ako na serveru radi nekoliko lokacija, a svaka od njih ima svoje vremensko ograničenje neaktivnosti korisnika, tada će postavljanje ovog parametra na jednu od lokacija dovesti do njegovog podešavanja za druge stranice. Isto važi i za dijeljeni hosting. Da bi se izbjegla ova situacija, odvojeni direktoriji sesije se koriste za svaku lokaciju unutar istog poslužitelja. Postavljanje putanje do direktorija sesija se vrši pomoću parametra session.save_path u datoteci postavki php.ini ili pozivom funkcije ini_set(). Nakon toga, sesije svake lokacije će biti pohranjene u odvojenim direktorijima, a session.gc_maxlifetime parametar postavljen na jednoj od lokacija bit će važeći samo za njegovu sesiju. Ovaj slučaj nećemo detaljno razmatrati, pogotovo jer imamo fleksibilniju opciju za praćenje neaktivnosti korisnika.

Kontrola neaktivnosti korisnika pomoću varijabli sesije Čini se da prethodna opcija, uz svu svoju jednostavnost (samo nekoliko dodatnih linija koda), daje sve što nam je potrebno. Ali što ako se svaki zahtjev ne može smatrati rezultatom aktivnosti korisnika? Na primjer, stranica ima tajmer koji povremeno šalje AJAX zahtjev za primanje ažuriranja sa servera. Takav zahtjev se ne može smatrati aktivnošću korisnika, što znači da automatsko produžavanje vijeka trajanja sesije nije ispravno u ovom slučaju. Ali znamo da PHP automatski ažurira vreme modifikacije fajla sesije svaki put kada se pozove funkcija session_start(), što znači da će svaki zahtev dovesti do produženja životnog veka sesije, a vremensko ograničenje neaktivnosti korisnika nikada neće nastupiti. Osim toga, posljednja napomena iz prethodnog odjeljka o zamršenosti parametra session.gc_maxlifetime nekima može izgledati previše zbunjujuće i teško za implementaciju.

Da bismo riješili ovaj problem, napustit ćemo korištenje ugrađenih PHP mehanizama i uvesti nekoliko novih varijabli sesije koje će nam omogućiti da sami kontroliramo vrijeme neaktivnosti korisnika.

Funkcija startSession($isUserActivity=true) ($sessionLifetime = 300; if (session_id()) vrati true; // Postavite životni vijek kolačića prije zatvaranja pretraživača (sve ćemo kontrolirati na strani servera) ini_set("session. cookie_lifetime", 0) ; if (! session_start()) vrati false; $t = time(); if ($sessionLifetime) ( // Ako je postavljeno vremensko ograničenje neaktivnosti korisnika, // provjerite vrijeme koje je proteklo od posljednje aktivnosti korisnika // (vrijeme posljednjeg zahtjeva kada je varijabla sesije lastactivity ažurirana) if (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // Ako je vrijeme proteklo od posljednja aktivnost korisnika, / / ​​je veća od vremenskog ograničenja neaktivnosti, što znači da je sesija istekla i da morate prekinuti sesiju destroySession(); return false; ) else ( // Ako vremensko ograničenje još nije nastupilo, // i ako je zahtjev došao kao rezultat aktivnosti korisnika, // ažurirajte varijablu lastactivity s vrijednošću trenutnog vremena, // čime se produžuje vrijeme sesije za još jednu sessionLifetime sekundi if ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) return true; )

Hajde da sumiramo. U svakom zahtjevu provjeravamo da li je došlo do isteka vremena od posljednje aktivnosti korisnika do trenutnog trenutka, a ako je dostignuto, uništavamo sesiju i prekidamo izvršavanje funkcije, vraćajući FALSE. Ako vremensko ograničenje nije dostignuto, a parametar $isUserActivity sa vrijednošću TRUE je proslijeđen funkciji, ažuriramo vrijeme posljednje aktivnosti korisnika. Sve što treba da uradimo je da u skripti za pozivanje odredimo da li je zahtev rezultat aktivnosti korisnika, a ako nije, pozvati funkciju startSession sa parametrom $isUserActivity postavljenim na FALSE.

Dodatak od 07.06.2013. Obrada rezultata funkcije sessionStart().

Komentari su istakli da vraćanje FALSE ne daje potpuno razumijevanje uzroka greške, i to je apsolutno pošteno. Ovdje nisam objavio detaljno rukovanje greškama (dužina članka je već prilično velika), jer to nije direktno povezano s temom članka. Ali s obzirom na komentare, razjasnit ću.

Kao što vidite, funkcija sessionStart može vratiti FALSE u dva slučaja. Ili se sesija nije mogla pokrenuti zbog nekih internih grešaka na serveru (na primjer, pogrešne postavke sesije u php.ini), ili je životni vijek sesije istekao. U prvom slučaju moramo preusmjeriti korisnika na stranicu sa greškom u kojoj se navodi da postoje problemi na serveru i obrazac za kontaktiranje podrške. U drugom slučaju, moramo prenijeti korisnika na obrazac za prijavu i u njemu prikazati odgovarajuću poruku da je sesija istekla. Da bismo to učinili, trebamo unijeti kodove grešaka i vratiti odgovarajući kod umjesto FALSE, a u metodi pozivanja provjeriti i postupiti u skladu s tim.

Sada, čak i ako sesija na serveru i dalje postoji, bit će uništena prvi put kada joj se pristupi ako je isteklo korisničko vrijeme neaktivnosti. I to će se dogoditi bez obzira na to koji je vijek trajanja sesije postavljen u globalnim PHP postavkama.

Napomena: Šta se dešava ako je pretraživač zatvoren, a kolačić imena sesije automatski uništen? Zahtjev serveru sljedeći put kada se pretraživač otvori neće sadržavati kolačiće sesije, a server neće moći otvoriti sesiju i provjeriti vremensko ograničenje neaktivnosti korisnika. Za nas je ovo ekvivalentno stvaranju nove sesije i ni na koji način ne utiče na funkcionalnost ili sigurnost. Ali postavlja se pošteno pitanje - ko će onda uništiti staru sesiju, ako smo je do sada uništili nakon isteka vremena? Ili će sada visiti u direktoriju sesija zauvijek? Za čišćenje starih sesija u PHP-u postoji mehanizam koji se zove sakupljanje smeća. Pokreće se u vrijeme sljedećeg zahtjeva serveru i briše sve stare sesije na osnovu datuma posljednje izmjene datoteka sesije. Ali mehanizam prikupljanja smeća ne počinje sa svakim zahtjevom prema serveru. Učestalost (tačnije, vjerovatnoća) pokretanja određena je sa dva parametra podešavanja session.gc_probability i session.gc_divisor. Rezultat dijeljenja prvog parametra sa drugim je vjerovatnoća pokretanja mehanizma za sakupljanje smeća. Dakle, da bi se mehanizam za brisanje sesije pokrenuo sa svakim zahtjevom prema serveru, ovi parametri moraju biti postavljeni na jednake vrijednosti, na primjer “1”. Ovaj pristup garantuje čist direktorij sesije, ali je očigledno preskup za server. Stoga je na proizvodnim sistemima zadana vrijednost session.gc_divisor postavljena na 1000, što znači da će se mehanizam prikupljanja smeća pokrenuti s vjerovatnoćom od 1/1000. Ako eksperimentirate sa ovim postavkama u vašoj php.ini datoteci, možda ćete primijetiti da u gore opisanom slučaju, kada pretraživač zatvori i obriše sve svoje kolačiće, još neko vrijeme ostaju stare sesije u direktoriju sesija. Ali ovo ne bi trebalo da vas brine, jer... kao što je već rečeno, to ni na koji način ne utiče na sigurnost našeg mehanizma.

Ažuriranje od 07.06.2013. Sprečavanje zamrzavanja skripti zbog zaključavanja fajla sesije

Komentari su pokrenuli pitanje zamrzavanja istovremenog pokretanja skripti zbog blokiranja fajla sesije (najupečatljivija opcija je duga anketa).

Za početak, napominjem da ovaj problem ne ovisi direktno o opterećenju servera ili broju korisnika. Naravno, što je više zahtjeva, to se skripte izvode sporije. Ali ovo je indirektna zavisnost. Problem se javlja samo unutar jedne sesije, kada server primi nekoliko zahtjeva u ime jednog korisnika (npr. jedan od njih je duga anketa, a ostali su redovni zahtjevi). Svaki zahtjev pokušava pristupiti istoj datoteci sesije, a ako prethodni zahtjev nije otključao datoteku, sljedeći će stajati čekajući.

Da bi zaključavanje datoteke sesije bilo na minimumu, snažno se preporučuje da zatvorite sesiju pozivanjem funkcije session_write_close() odmah nakon što se sve radnje s varijablama sesije dovrše. U praksi, to znači da ne biste trebali sve pohranjivati ​​u varijablama sesije i pristupati im tokom izvršavanja skripte. A ako trebate pohraniti neke radne podatke u varijable sesije, onda ih pročitajte odmah kada sesija počne, spremite ih u lokalne varijable za kasniju upotrebu i zatvorite sesiju (što znači zatvaranje sesije pomoću funkcije session_write_close, a ne uništavanje pomoću session_destroy ).

U našem primjeru, to znači da odmah nakon otvaranja sesije, provjere njenog životnog vijeka i postojanja ovlaštenog korisnika, moramo pročitati i spremiti sve dodatne varijable sesije koje zahtijeva aplikacija (ako ih ima), a zatim zatvoriti sesiju pozivom na session_write_close() i nastavite izvršavanje skripte, bilo da se radi o dugoj anketi ili redovnom zahtjevu.

Zaštita sesija od neovlaštene upotrebe Zamislimo situaciju. Jedan od vaših korisnika dobije trojanca koji pljačka kolačiće pretraživača (u kojem je pohranjena naša sesija) i šalje ga na navedenu e-poštu. Napadač dobiva kolačić i koristi ga za lažiranje zahtjeva u ime našeg ovlaštenog korisnika. Server uspješno prihvaća i obrađuje ovaj zahtjev kao da je došao od ovlaštenog korisnika. Ukoliko se ne provede dodatna provjera IP adrese, takav napad će dovesti do uspješnog hakovanja korisničkog računa sa svim posljedicama koje proizilaze.

Zašto je to bilo moguće? Očigledno, zato što su ime i identifikator sesije uvijek isti tokom cijelog životnog vijeka sesije, i ako primite ove podatke, lako možete slati zahtjeve u ime drugog korisnika (naravno, u toku trajanja ove sesije). Ovo možda nije najčešći tip napada, ali teoretski se čini sasvim izvodljivim, pogotovo ako se uzme u obzir da takvom trojancu nisu potrebna ni administratorska prava da bi opljačkao kolačiće pretraživača korisnika.

Kako se možete zaštititi od napada ove vrste? Opet, očito, ograničavanjem životnog vijeka identifikatora sesije i periodičnom promjenom identifikatora unutar iste sesije. Također možemo promijeniti naziv sesije tako što ćemo potpuno izbrisati staru i kreirati novu sesiju, kopirajući sve varijable sesije iz stare u nju. Ali to ne utiče na suštinu pristupa, pa ćemo se zbog jednostavnosti ograničiti samo na identifikator sesije.

Jasno je da što je kraći životni vijek ID-a sesije, to će napadač imati manje vremena da dobije i koristi kolačiće da krivotvori korisnički zahtjev. U idealnom slučaju, novi identifikator treba koristiti za svaki zahtjev, što će minimizirati mogućnost korištenja tuđe sesije. Ali mi ćemo razmotriti opći slučaj kada je vrijeme regeneracije identifikatora sesije postavljeno proizvoljno.

(Izostavićemo dio koda o kojem je već bilo riječi).

Funkcija startSession($isUserActivity=true) ( ​​// Životni vijek identifikatora sesije $idLifetime = 60; ... if ($idLifetime) ( // Ako je vijek trajanja identifikatora sesije postavljen, // provjerite vrijeme koje je proteklo od početka sesije kreirana ili zadnja regeneracija // (vrijeme posljednjeg zahtjeva kada je varijabla početka sesije ažurirana) if (isset($_SESSION["starttime"])) ( if ($t-$_SESSION["starttime"] >= $ idLifetime) ( // Vrijeme je istekao vijek trajanja identifikatora sesije // Generiraj novi identifikator session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( // Doći ćemo ovdje ako je sesija upravo imala kreirano // Postavite vrijeme za generiranje identifikatora sesije na trenutno vrijeme $_SESSION["starttime"] = $t; ) ) return true; )

Dakle, prilikom kreiranja nove sesije (koja se dešava kada se korisnik uspješno prijavi), postavljamo varijablu sesije starttime, koja nam pohranjuje vrijeme posljednje generacije identifikatora sesije, na vrijednost jednaku trenutnom vremenu servera. Zatim u svakom zahtjevu provjeravamo da li je prošlo dovoljno vremena (idLifetime) od posljednje generacije identifikatora i ako jeste, generiramo novi. Dakle, ako tokom postavljenog vijeka trajanja identifikatora napadač koji je primio kolačić ovlaštenog korisnika nema vremena da ga koristi, server će lažni zahtjev smatrati neovlaštenim, a napadač će biti odveden na stranicu za prijavu. .

Napomena: Novi ID sesije ulazi u kolačić pretraživača kada se pozove funkcija session_regenerate_id(), koja šalje novi kolačić, slično funkciji session_start(), tako da ne moramo sami da ažuriramo kolačić.

Ako želimo da naše sesije učinimo što sigurnijim, dovoljno je postaviti vijek trajanja identifikatora na jedan ili čak ukloniti funkciju session_regenerate_id() iz zagrada i ukloniti sve provjere, što će dovesti do regeneracije identifikatora u svakom zahtjev. (Nisam testirao uticaj ovog pristupa na performanse, i mogu samo reći da funkcija session_regenerate_id(true) u suštini obavlja samo 4 radnje: generisanje novog identifikatora, kreiranje zaglavlja sa kolačićem sesije, brisanje starog i kreiranje novu datoteku sesije).

Lirska digresija: Ako se trojanac pokaže toliko pametnim da napadaču ne šalje kolačiće, već organizira slanje unaprijed pripremljenog lažnog zahtjeva odmah po prijemu kolačića, gore opisani metod najvjerovatnije neće moći zaštitite se od takvog napada, jer između vremena kada trojanac primi kolačić i slanja lažnog zahtjeva, praktično neće biti razlike, a postoji velika vjerovatnoća da u ovom trenutku identifikator sesije neće biti regeneriran.

Mogućnost istovremenog rada u jednom pretraživaču u ime više korisnika Poslednji zadatak koji bih želeo da razmotrim je mogućnost istovremenog rada više korisnika u jednom pretraživaču. Ova funkcija je posebno korisna u fazi testiranja, kada trebate emulirati istovremeni rad korisnika, a preporučljivo je to učiniti u svom omiljenom pregledniku, umjesto da koristite cijeli raspoloživi arsenal ili otvarate nekoliko instanci preglednika u anonimnom načinu rada. .

U našim prethodnim primjerima nismo eksplicitno specificirali naziv sesije, pa je korišteno zadano PHP ime (PHPSESSID). To znači da su sve sesije koje smo do sada kreirali poslale kolačić u pretraživač pod imenom PHPSESSID. Očigledno, ako je naziv kolačića uvijek isti, onda ne postoji način da se organiziraju dvije sesije s istim imenom unutar istog pretraživača. Ali kada bismo koristili vlastito ime sesije za svakog korisnika, problem bi bio riješen. Učinimo to.

Funkcija startSession($isUserActivity=true, $prefix=null) ( ... if (session_id()) vrati true; // Ako je korisnički prefiks proslijeđen u parametrima, // postavite jedinstveni naziv sesije koji uključuje ovo prefiks, // inače postavite zajedničko ime za sve korisnike (na primjer, MYPROJECT) session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) vrati false; ... )

Sada sve što preostaje je osigurati da skripta za pozivanje prosljeđuje jedinstveni prefiks za svakog korisnika funkciji startSession(). To se može učiniti, na primjer, prosljeđivanjem prefiksa u GET/POST parametrima svakog zahtjeva ili putem dodatnog kolačića.

Zaključak U zaključku ću dati kompletan konačni kod naših funkcija za rad sa PHP sesijama, uključujući sve zadatke o kojima smo gore govorili.

Funkcija startSession($isUserActivity=true, $prefix=null) ( $sessionLifetime = 300; $idLifetime = 60; if (session_id()) vrati true; session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) vrati false; $t = time(); if ($sessionLifetime) ( if (isset($_SESSION["lastactivity"] ) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( destroySession(); vrati 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; ) ) vrati true; ) funkcija destroySession() ( if (session_id()) ( session_unset(); setcookie(session_name(), session_id(), time() -60*60*24); session_destroy(); ) )

Nadam se da će ovaj članak uštedjeti malo vremena onima koji nikada nisu previše ulazili u mehanizam sesije, i dati dovoljno uvida u ovaj mehanizam onima koji tek počinju da se upoznaju sa PHP-om.

Trebate li korisničko ime i lozinku?

Da biste poslali članke online i provjerili status poslanih članaka, morate se registrirati i prijaviti na svoj račun.

Kontrolna lista za pripremu članka za podnošenje

Kao dio procesa podnošenja članka, autori moraju provjeriti da li njihov članak ispunjava sve sljedeće tačke; članci se mogu vratiti autorima ako ne ispunjavaju ove zahtjeve.

Članak je pripremljen u skladu sa zahtjevima

Uslovi prenosa autorskih prava

Autori zadržavaju autorska prava nad djelom i dodjeljuju časopisu prava na prvu publikaciju zajedno s djelom, dok ga licenciraju pod uslovima Creative Commons licence za pripisivanje, što drugima omogućava da distribuiraju ovo djelo uz obavezno navođenje autora djela i vezu na originalnu publikaciju u ovom časopisu.

Izjava o privatnosti

Imena i adrese e-pošte unesene na web stranicu ovog časopisa koristit će se isključivo u svrhe koje je odredio ovaj časopis i neće se koristiti u bilo koju drugu svrhu niti će se dati bilo kojoj drugoj osobi ili entitetu.

Prije registracije u sustav, korisnik se slaže sa politikom obrade i čuvanja ličnih podataka.

Autorska plaćanja

1500 znakova sa razmacima: 300,00 (RUB)

Objavljivanje 1 stranice rukopisa (1500 znakova) - 300 rubalja. Grafički materijali / stolovi se plaćaju zasebno - 50 rubalja / 1 komad. Autorski primjerak, uključujući dostavu unutar Rusije, plaća se na zahtjev autora - 400 rubalja. Dostava u inostranstvo - 800 rubalja. Trošak slanja potvrde o prihvatanju materijala za objavljivanje iznosi 150 rubalja.

Prevod pratećih informacija (puno ime, mjesto rada autora; naslov; sažetak; ključne riječi) na engleski 0,5 rubalja za svaki znak, uključujući razmake.

Pažnja! Autori (kandidati i doktori nauka) koji, prema elibrary.ru, imaju 300 ili više citata (udio samocitata ne smije biti veći od 30%), objavljuju se besplatno. Ako ispunjavate uslove za besplatnu publikaciju, prilikom slanja materijala u polju za komentare navedite link do profila vaše biblioteke sa brojem citata. Troškovi dostave za preuzimanje plaćaju se posebno.

Sigurnost web stranice zasniva se na upravljanju sesijama. Kada se korisnik poveže na sigurnu stranicu, on daje vjerodajnice, obično u obliku korisničkog imena i lozinke. Web server nema pojma koji korisnik je već prijavljen ili kako se kreće od stranice do stranice. Mehanizam sesije sprječava korisnike da moraju unositi lozinku svaki put kada žele izvršiti novu radnju ili otići na novu stranicu.

U suštini, upravljanje sesijom osigurava da je trenutno povezani korisnik onaj koji je autentificiran. Ali nažalost, sesije su postale očigledna meta za hakere jer mogu dozvoliti pristup web serveru bez potrebe za autentifikacijom.

Nakon autentifikacije korisnika, web server mu daje ID sesije. Ovaj ID se pohranjuje u pretraživaču i zamjenjuje se kad god je potrebna autentifikacija. Ovo vam omogućava da izbjegnete ponovljene procese unosa prijave/lozinke. Sve se to događa u pozadini i ne uzrokuje nelagodu korisniku. Zamislite da unesete svoje korisničko ime i lozinku svaki put kada pogledate novu stranicu!

U ovom članku pokušaću da opišem sve načine koje znam da zaštitim ID sesije u PHP-u.

Korištenje kolačića Prema zadanim postavkama, sve informacije o sesiji, uključujući ID, šalju se kolačiću. Ali to se ne dešava uvek. Neki korisnici onemogućuju kolačiće u svojim pretraživačima. U ovom slučaju, pretraživač će proslijediti ID sesije u URL-u.

Ovdje se ID prenosi u čistom tekstu, za razliku od sesije putem kolačića, kada su informacije skrivene u HTTP zaglavlju. Najjednostavniji način zaštite od ovoga bio bi zabrana prijenosa identifikatora sesije kroz adresnu traku. Ovo se može uraditi tako što ćete napisati sljedeće u konfiguracijski fajl Apache servera .htaccess:

Php_flag session.use_only_cookies uključen

Korišćenje šifrovanja Ako vaša lokacija mora da obrađuje osetljive informacije, kao što su brojevi kreditnih kartica (pozdrav od Sonyja), trebalo bi da koristite SSL3.0 ili TSL1.0 enkripciju. Da biste to učinili, kada postavljate kolačić, morate navesti true za sigurnosni parametar.

Ako pohranite lozinku sesije u varijablu $_SESSION (ipak je bolje koristiti sql), onda je ne biste trebali pohranjivati ​​u čistom tekstu.

If ($_SESSION["password"] == $userpass) ( // kod)

Gornji kod nije siguran jer je lozinka pohranjena kao običan tekst u varijabli sesije. Umjesto toga, koristite md5 enkripciju, otprilike ovako:

If ($_SESSION["md5password"] == md5($userpass)) ( // kod)

Provjera pretraživača Da biste spriječili mogućnost korištenja sesije iz drugog pretraživača (računara), trebate unijeti provjeru HTTP zaglavlja korisničkog agenta:

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

Istek sesije Ograničite životni vijek sesije, kao i vrijeme isteka kolačića. Podrazumevano, trajanje sesije je 1440 sekundi. Ovu vrijednost možete promijeniti putem php.ini i .htaccess. Primjer za .htaccess:

# Životni vijek sesije u sekundama
php_value session.gc_maxlifetime 3600
# Životni vijek kolačića u sekundama
php_value session.cookie_lifetime 3600

Vezivanje prema IP adresi U određenim situacijama (ne uvijek), trebali biste se vezati po IP adresi. Uglavnom kada je broj korisnika ograničen i imaju statične IP adrese. Provjera može biti zasnovana na listi dozvoljenih IP adresa,

Include("ip_list.php"); //$ip_white_list = niz ("admin1" => "111.222.333.444", "admin2" => "555.666.777.888"); if(!empty(array_search($_SERVER["REMOTE_ADDR"],$ip_white_list))) ( header("Lokacija: admin.php"); ) else ( echo "ZABRANI PRISTUP!"; )

Ili po IP adresi za svaki zahtjev (samo za statičku IP adresu):

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

Morate biti svjesni da se hakovanje ne može u potpunosti izbjeći. Ovaj hak možete učiniti što je moguće težim na bilo koji poznati način. Međutim, ne zaboravite ni na svoje legalne korisnike, kako im ne biste zakomplikovali život takvom zaštitom.

Ovaj članak je napisan 2009. godine i ostaje jedan od naših najpopularnijih postova. Ako želite da saznate više o PHP-u i MySQL-u, ovo bi moglo biti od velikog interesa.

NAPOMENA: Ovaj članak je nedavno ažuriran da radi na PHP 4.2 ili novijoj!

Nedavno sam imao priliku da radim na jednom malom projektu sa grupom ljudi. Rano smo utvrdili da sama e-poruka neće biti dovoljna da svi budu u toku, pa sam dobio zadatak da napravim malu web stranicu za projekat. Sadržao bi jednostavnu tablu za poruke, mjesto na koje bismo mogli učitati dokumente i druge fajlove za korištenje ostatku tima, te kontakt informacije za različite članove tima.

Da bi mnoge od ovih funkcija funkcionirale, znao sam da će mi trebati korisnici da se prijave prije pristupanja relevantnim dijelovima stranice. Ono što mi je trebalo je sistem koji bi omogućio korisnicima da se registruju za korisnički ID za pristup sajtu, a zatim odmah koriste taj ID bez ikakve moje intervencije.

U ovom članku ću dati pregled sistema koji sam razvio, počevši od prve polovine procesa registracije korisnika. U drugoj polovini, fokusirat ću se na samu stranicu, kako ona zahtijeva od korisnika da se prijave, a zatim održava taj status prijavljenog tijekom svoje posjete. Posebno ću obratiti pažnju na korištenje funkcija upravljanja sesijama u PHP-u. Na kraju, trebali biste imati sve informacije koje su vam potrebne za implementaciju sličnog vlastitog sistema.

U ovom članku pretpostaviću da imate osnovno poznavanje PHP jezika, upotrebu obrazaca za slanje informacija u PHP skriptu i kako se PHP može koristiti za interakciju sa MySQL bazom podataka. Ako vam je bilo koji od ovih pojmova strani koncept, trebali biste početi čitanjem mog prethodnog članka, .

Prvi dio: Proces registracije Obrazac za registraciju

Prirodno mjesto za početak izgradnje stranice koja će zahtijevati od korisnika da se registruju za pristup je sam proces registracije. Kao što bi se očekivalo, jednostavan obrazac zasnovan na webu će učiniti trik. Evo kako će to izgledati:

A evo i koda za ovaj obrazac:




Registracija novog korisnika



Obrazac za registraciju novog korisnika

* označava obavezno polje


Pošto je cilj sada jasan, provest ću vas kroz kod za accesscontrol.php. Počnite tako što ćete uključiti svoja dva zgodna uključena fajla: