Proteksyon ng Session ID sa PHP. Mga pitfalls ng paggamit ng mga session sa PHP Pagpasa ng value o array gamit ang PHP session

Pagbati, mahal na pamayanan.

Una sa lahat, nais kong pasalamatan ka para sa isang napaka-kapaki-pakinabang na mapagkukunan. Higit sa isang beses nakakita ako ng maraming kawili-wiling ideya at praktikal na payo dito.

Ang layunin ng artikulong ito ay i-highlight ang mga pitfalls ng paggamit ng mga session sa PHP. Siyempre, mayroong dokumentasyon ng PHP at maraming mga halimbawa, at ang artikulong ito ay hindi nilayon na maging isang kumpletong gabay. Ito ay dinisenyo upang ipakita ang ilan sa mga nuances ng pagtatrabaho sa mga session at protektahan ang mga developer mula sa hindi kinakailangang pag-aaksaya ng oras.

Ang pinakakaraniwang halimbawa ng paggamit ng mga session ay, siyempre, pahintulot ng user. Magsimula tayo sa pinakapangunahing pagpapatupad upang unti-unting mapaunlad ito habang may mga bagong gawain.

(Upang makatipid ng espasyo at oras, lilimitahan namin ang aming mga halimbawa sa mga function lamang ng session, sa halip na bumuo dito ng isang ganap na application ng pagsubok na may magandang hierarchy ng klase, komprehensibong paghawak ng error at iba pang magagandang bagay).

Function startSession() ( // Kung nasimulan na ang session, itigil ang pag-execute at ibalik ang TRUE // (dapat hindi pinagana ang session.auto_start parameter sa php.ini settings file - ang default na value) kung bumalik ang (session_id()) true; else return session_start(); // Tandaan: Bago ang bersyon 5.3.0, ang session_start() function ay nagbalik ng TRUE kahit na may naganap na error. // Kung gumagamit ka ng bersyon bago ang 5.3.0, magsagawa ng karagdagang pagsusuri para sa session_id() // pagkatapos tawagan ang session_start() ) function destroySession() ( if (session_id()) ( // Kung may aktibong session, tanggalin ang session cookies, setcookie(session_name(), session_id(), time( )-60*60*24); // at sirain ang session session_unset( ); session_destroy(); ) )

Tandaan: Ipinapalagay na ang mambabasa ay may pangunahing kaalaman sa mga session ng PHP, kaya hindi namin sasaklawin ang prinsipyo ng pagpapatakbo ng session_start() at session_destroy() function dito. Ang mga gawain ng layout ng form sa pag-login at pagpapatunay ng user ay hindi nauugnay sa paksa ng artikulo, kaya aalisin din namin ang mga ito. Ipaalala ko lang sa iyo na para matukoy ang user sa bawat kasunod na kahilingan, sa sandali ng matagumpay na pag-log in, kailangan naming iimbak ang user identifier sa isang variable ng session (pinangalanang userid, halimbawa), na magiging available sa lahat ng kasunod na kahilingan sa loob ng ang buhay ng sesyon. Kinakailangan din na ipatupad ang pagpoproseso ng resulta ng aming startSession() function. Kung ang function ay nagbabalik ng FALSE, ipakita ang login form sa browser. Kung ang function ay nagbalik ng TRUE, at isang variable ng session na naglalaman ng identifier ng awtorisadong user (sa aming kaso - userid), ay umiiral - ipakita ang pahina ng awtorisadong user (para sa higit pang impormasyon tungkol sa paghawak ng error, tingnan ang karagdagan na may petsang 2013-06- 07 sa seksyon sa mga variable ng session).

Sa ngayon ay malinaw na ang lahat. Magsisimula ang mga tanong kapag kailangan mong ipatupad ang kontrol sa kawalan ng aktibidad ng user (timeout ng session), paganahin ang maraming user na gumana nang sabay-sabay sa isang browser, at protektahan din ang mga session mula sa hindi awtorisadong paggamit. Ito ay tatalakayin sa ibaba.

Pagkontrol sa kawalan ng aktibidad ng user gamit ang built-in na mga tool sa PHP Ang unang tanong na madalas na lumitaw sa mga developer ng iba't ibang console para sa mga user ay ang awtomatikong pagwawakas ng session kung sakaling hindi aktibo sa bahagi ng user. Walang mas madali kaysa gawin ito gamit ang mga built-in na kakayahan ng PHP. (Ang pagpipiliang ito ay hindi partikular na maaasahan o nababaluktot, ngunit isasaalang-alang namin ito para sa pagkakumpleto).

Function startSession() ( // Inactivity timeout ng user (sa mga segundo) $sessionLifetime = 300; if (session_id()) return true; // Itakda ang cookie lifetime ini_set("session.cookie_lifetime", $sessionLifetime); // Kung user nakatakda ang inactivity timeout, itakda ang habambuhay ng session sa server // Tandaan: Para sa isang production server, inirerekomendang i-preset ang mga parameter na ito sa php.ini file kung ($sessionLifetime) ini_set("session.gc_maxlifetime", $sessionLifetime) ; kung (session_start( )) ( setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; ) else ibalik ang false; )

Ilang paglilinaw. Tulad ng alam mo, tinutukoy ng PHP kung aling session ang kailangang ilunsad sa pamamagitan ng pangalan ng cookie na ipinadala ng browser sa header ng kahilingan. Ang browser, sa turn, ay tumatanggap ng cookie na ito mula sa server, kung saan inilalagay ito ng session_start() function. Kung nag-expire na ang cookie ng browser, hindi ito ipapadala sa kahilingan, na nangangahulugang hindi matutukoy ng PHP kung aling session ang magsisimula at ituturing ito bilang paglikha ng bagong session. Ang parameter ng mga setting ng PHP session.gc_maxlifetime, na nakatakdang katumbas ng timeout ng hindi aktibo ng user, ay nagtatakda ng tagal ng isang session ng PHP at kinokontrol ng server. Ang pagkontrol sa habambuhay ng session ay gumagana tulad ng sumusunod (dito isinasaalang-alang namin ang isang halimbawa ng pag-iimbak ng mga session sa mga pansamantalang file bilang ang pinakakaraniwan at default na opsyon sa PHP).

Kapag ang isang bagong session ay ginawa, ang isang file na pinangalanang sess_ ay nilikha sa direktoryo na itinakda bilang ang direktoryo para sa pag-iimbak ng mga session sa mga setting ng PHP parameter session.save_path, kung saan ay ang session identifier. Susunod, sa bawat kahilingan, sa oras ng paglulunsad ng umiiral nang session, ina-update ng PHP ang oras ng pagbabago ng file na ito. Kaya, sa bawat kasunod na kahilingan, ang PHP, sa pamamagitan ng pagkakaiba sa pagitan ng kasalukuyang oras at oras ng huling pagbabago ng session file, ay maaaring matukoy kung ang session ay aktibo o ang buhay nito ay nag-expire na. (Ang mekanismo para sa pagtanggal ng mga lumang file ng session ay tinalakay nang mas detalyado sa susunod na seksyon.)

Tandaan: Dapat tandaan dito na ang session.gc_maxlifetime parameter ay nalalapat sa lahat ng session sa loob ng isang server (mas tiyak, sa loob ng isang pangunahing proseso ng PHP). Sa pagsasagawa, nangangahulugan ito na kung maraming mga site ang tumatakbo sa server, at ang bawat isa sa kanila ay may sariling timeout ng hindi aktibo ng user, kung gayon ang pagtatakda ng parameter na ito sa isa sa mga site ay hahantong sa setting nito para sa iba pang mga site. Ang parehong naaangkop sa shared hosting. Upang maiwasan ang sitwasyong ito, ang mga hiwalay na direktoryo ng session ay ginagamit para sa bawat site sa loob ng parehong server. Ang pagtatakda ng landas sa direktoryo ng mga session ay ginagawa gamit ang session.save_path na parameter sa php.ini settings file, o sa pamamagitan ng pagtawag sa ini_set() function. Pagkatapos nito, ang mga session ng bawat site ay maiimbak sa magkakahiwalay na mga direktoryo, at ang session.gc_maxlifetime parameter na itinakda sa isa sa mga site ay magiging wasto lamang para sa session nito. Hindi namin isasaalang-alang ang kasong ito nang detalyado, lalo na dahil mayroon kaming mas nababaluktot na opsyon para sa pagsubaybay sa kawalan ng aktibidad ng user.

Pagkontrol sa kawalan ng aktibidad ng user gamit ang mga variable ng session Mukhang ang nakaraang opsyon, para sa lahat ng pagiging simple nito (isang pares ng mga karagdagang linya ng code), ay nagbibigay ng lahat ng kailangan namin. Ngunit paano kung hindi lahat ng kahilingan ay maituturing na resulta ng aktibidad ng user? Halimbawa, ang isang page ay may timer na pana-panahong gumagawa ng kahilingan sa AJAX na makatanggap ng mga update mula sa server. Ang naturang kahilingan ay hindi maaaring ituring bilang aktibidad ng user, na nangangahulugan na ang awtomatikong pagpapahaba ng buhay ng session ay hindi tama sa kasong ito. Ngunit alam namin na awtomatikong ina-update ng PHP ang oras ng pagbabago ng session file sa tuwing tatawagin ang function na session_start(), na nangangahulugan na ang anumang kahilingan ay hahantong sa pagpapalawig ng buhay ng session, at hindi na mangyayari ang timeout ng kawalan ng aktibidad ng user. Bilang karagdagan, ang huling tala mula sa nakaraang seksyon tungkol sa mga intricacies ng session.gc_maxlifetime parameter ay maaaring mukhang masyadong nakakalito at mahirap ipatupad para sa ilan.

Upang malutas ang problemang ito, aabandonahin namin ang paggamit ng mga built-in na mekanismo ng PHP at magpapakilala ng ilang bagong variable ng session na magbibigay-daan sa aming kontrolin ang oras ng kawalan ng aktibidad ng user.

Function startSession ($isUserActivity=true) ($sessionLifetime = 300; if (session_id()) return true; // Itakda ang buhay ng cookie bago isara ang browser (kokontrolin namin ang lahat sa gilid ng server) ini_set("session. cookie_lifetime", 0); if (! session_start()) return false; $t = time(); if ($sessionLifetime) ( // Kung nakatakda ang timeout ng inactivity ng user, // check ang oras na lumipas mula noong huling aktibidad ng user // (huling kahilingan kung kailan na-update ang lastactivity session variable) if (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // Kung lumipas ang oras mula noong ang huling aktibidad ng user, / / ​​ay mas malaki kaysa sa inactivity timeout, na nangangahulugan na ang session ay nag-expire na at kailangan mong wakasan ang session destroySession(); return false; ) else ( // Kung ang timeout ay hindi pa nagaganap, // at kung ang kahilingan ay dumating bilang isang resulta ng aktibidad ng user, // i-update ang lastactivity variable na may halaga ng kasalukuyang isang beses, // at sa gayon ay pinahaba ang oras ng session ng isa pang sessionLifetime segundo kung ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) bumalik ng totoo; )

I-summarize natin. Sa bawat kahilingan, sinusuri namin kung naabot na ang timeout mula noong huling aktibidad ng user hanggang sa kasalukuyang sandali, at kung naabot na ito, sinisira namin ang session at naaantala ang pagsasagawa ng function, na nagbabalik ng FALSE. Kung hindi pa naabot ang timeout, at ang parameter na $isUserActivity na may value na TRUE ay ipinasa sa function, ina-update namin ang oras ng huling aktibidad ng user. Ang kailangan lang nating gawin ay tukuyin sa script ng pagtawag kung ang kahilingan ay resulta ng aktibidad ng user, at kung hindi, tawagan ang startSession function na may $isUserActivity parameter na nakatakda sa FALSE.

Pagdaragdag mula 2013-06-07 Pinoproseso ang resulta ng sessionStart() function

Itinuro ng mga komento na ang pagbabalik ng FALSE ay hindi nagbibigay ng kumpletong pag-unawa sa sanhi ng error, at ito ay ganap na patas. Hindi ako nag-publish ng detalyadong paghawak ng error dito (medyo malaki na ang haba ng artikulo), dahil hindi ito direktang nauugnay sa paksa ng artikulo. Ngunit sa mga komento, lilinawin ko.

Tulad ng nakikita mo, ang sessionStart function ay maaaring magbalik ng FALSE sa dalawang kaso. Maaaring hindi masimulan ang session dahil sa ilang internal na error sa server (halimbawa, maling mga setting ng session sa php.ini), o nag-expire na ang session lifetime. Sa unang kaso, dapat naming i-redirect ang user sa isang page na may error na nagsasaad na may mga problema sa server at isang form para sa pakikipag-ugnayan sa suporta. Sa pangalawang kaso, dapat naming ilipat ang user sa form sa pag-login at magpakita ng kaukulang mensahe dito na nagsasaad na ang session ay nag-expire na. Upang gawin ito, kailangan naming magpasok ng mga error code at ibalik ang kaukulang code sa halip na FALSE, at sa paraan ng pagtawag, suriin ito at kumilos nang naaayon.

Ngayon, kahit na mayroon pa ring session sa server, masisira ito sa unang pagkakataong ma-access ito kung nag-expire na ang inactivity timeout ng user. At ito ay mangyayari anuman ang habambuhay ng session na itinakda sa pandaigdigang mga setting ng PHP.

Tandaan: Ano ang mangyayari kung ang browser ay sarado at ang session name cookie ay awtomatikong nawasak? Ang kahilingan sa server sa susunod na bubuksan ang browser ay hindi maglalaman ng session cookie, at hindi mabubuksan ng server ang session at masuri ang inactivity timeout ng user. Para sa amin, ito ay katumbas ng paggawa ng bagong session at hindi nakakaapekto sa functionality o seguridad sa anumang paraan. Ngunit isang patas na tanong ang lumitaw - sino ang sisira sa lumang sesyon, kung hanggang ngayon ay sinisira natin ito pagkatapos mag-expire ang timeout? O mananatili ba ito sa direktoryo ng mga session magpakailanman? Upang linisin ang mga lumang session sa PHP, mayroong mekanismo na tinatawag na pangongolekta ng basura. Tumatakbo ito sa oras ng susunod na kahilingan sa server at iki-clear ang lahat ng lumang session batay sa huling petsa ng pagbabago ng mga file ng session. Ngunit ang mekanismo ng pagkolekta ng basura ay hindi nagsisimula sa bawat kahilingan sa server. Ang dalas (o sa halip, ang posibilidad) ng paglulunsad ay tinutukoy ng dalawang parameter ng mga setting session.gc_probability at session.gc_divisor. Ang resulta ng paghahati ng unang parameter sa pangalawa ay ang posibilidad ng paglulunsad ng mekanismo ng pangongolekta ng basura. Kaya, para mailunsad ang mekanismo ng pag-clear ng session sa bawat kahilingan sa server, dapat na itakda ang mga parameter na ito sa pantay na halaga, halimbawa "1". Ginagarantiyahan ng diskarteng ito ang isang malinis na direktoryo ng session, ngunit halatang masyadong mahal para sa server. Samakatuwid, sa mga system ng produksyon, ang default na halaga ng session.gc_divisor ay nakatakda sa 1000, na nangangahulugan na ang mekanismo ng pangongolekta ng basura ay tatakbo na may posibilidad na 1/1000. Kung mag-eksperimento ka sa mga setting na ito sa iyong php.ini file, maaari mong mapansin na sa kaso na inilarawan sa itaas, kapag isinara at na-clear ng browser ang lahat ng cookies nito, mayroon pa ring mga lumang session na natitira sa direktoryo ng mga session nang ilang sandali. Ngunit hindi ito dapat mag-alala sa iyo, dahil... gaya ng nasabi na, hindi ito nakakaapekto sa anumang paraan sa kaligtasan ng ating mekanismo.

Update mula 2013-06-07 Pag-iwas sa mga script mula sa pagyeyelo dahil sa pag-lock ng session file

Itinaas ng mga komento ang isyu ng sabay-sabay na pagpapatakbo ng mga script sa pagyeyelo dahil sa pagka-block ng session file (ang pinaka-kapansin-pansing opsyon ay mahabang poll).

Upang magsimula, tandaan ko na ang problemang ito ay hindi direktang nakasalalay sa pag-load ng server o sa bilang ng mga gumagamit. Siyempre, mas maraming kahilingan, mas mabagal ang mga script na naisakatuparan. Ngunit ito ay isang hindi direktang pag-asa. Ang problema ay lilitaw lamang sa loob ng isang session, kapag ang server ay nakatanggap ng ilang mga kahilingan sa ngalan ng isang user (halimbawa, isa sa mga ito ay mahabang poll, at ang iba ay mga regular na kahilingan). Ang bawat kahilingan ay sumusubok na i-access ang parehong session file, at kung ang nakaraang kahilingan ay hindi na-unlock ang file, pagkatapos ay ang kasunod na isa ay mag-hang naghihintay.

Upang mapanatili ang pag-lock ng session file sa pinakamababa, lubos na inirerekomenda na isara ang session sa pamamagitan ng pagtawag sa session_write_close() function kaagad pagkatapos makumpleto ang lahat ng pagkilos na may mga variable ng session. Sa pagsasagawa, nangangahulugan ito na hindi mo dapat iimbak ang lahat sa mga variable ng session at i-access ang mga ito sa buong pagpapatupad ng script. At kung kailangan mong mag-imbak ng ilang gumaganang data sa mga variable ng session, pagkatapos ay basahin kaagad ang mga ito kapag nagsimula ang session, i-save ang mga ito sa mga lokal na variable para magamit sa ibang pagkakataon at isara ang session (ibig sabihin, isara ang session gamit ang session_write_close function, at hindi sirain ito gamit ang session_destroy ).

Sa aming halimbawa, nangangahulugan ito na kaagad pagkatapos magbukas ng isang session, suriin ang buhay nito at ang pagkakaroon ng isang awtorisadong user, dapat naming basahin at i-save ang lahat ng karagdagang mga variable ng session na kinakailangan ng application (kung mayroon), pagkatapos ay isara ang session gamit ang isang tawag sa session_write_close() at ipagpatuloy ang pagpapatupad ng isang script, maging ito ay isang mahabang poll o isang regular na kahilingan.

Pagprotekta sa mga session mula sa hindi awtorisadong paggamit Mag-isip tayo ng isang sitwasyon. Ang isa sa iyong mga user ay nakakakuha ng Trojan na nagnanakaw sa cookies ng browser (kung saan nakaimbak ang aming session) at ipinapadala ito sa tinukoy na email. Nakukuha ng attacker ang cookie at ginagamit ito para madaya ang isang kahilingan sa ngalan ng aming awtorisadong user. Matagumpay na tinatanggap at pinoproseso ng server ang kahilingang ito na parang nagmula ito sa isang awtorisadong gumagamit. Kung ang karagdagang pag-verify ng IP address ay hindi ipinatupad, ang naturang pag-atake ay hahantong sa isang matagumpay na pag-hack ng account ng user kasama ang lahat ng mga kasunod na kahihinatnan.

Bakit naging posible ito? Malinaw, dahil ang pangalan at session identifier ay palaging pareho para sa buong buhay ng session, at kung matatanggap mo ang data na ito, madali kang makakapagpadala ng mga kahilingan sa ngalan ng isa pang user (siyempre, sa loob ng buhay ng session na ito). Maaaring hindi ito ang pinakakaraniwang uri ng pag-atake, ngunit sa teoryang ito ay tila posible, lalo na kung isasaalang-alang na ang naturang Trojan ay hindi nangangailangan ng mga karapatan ng administrator upang pagnakawan ang cookies ng browser ng gumagamit.

Paano mo mapoprotektahan ang iyong sarili mula sa ganitong uri ng pag-atake? Muli, malinaw naman, sa pamamagitan ng paglilimita sa buhay ng session identifier at pana-panahong pagbabago ng identifier sa loob ng parehong session. Mababago rin natin ang pangalan ng session sa pamamagitan ng ganap na pagtanggal sa luma at paggawa ng bagong session, pagkopya sa lahat ng variable ng session mula sa luma papunta dito. Ngunit hindi ito nakakaapekto sa kakanyahan ng diskarte, kaya para sa pagiging simple, lilimitahan lang natin ang ating sarili sa identifier ng session.

Malinaw na mas maikli ang buhay ng session ID, mas kaunting oras ang kakailanganin ng isang umaatake upang makakuha at gumamit ng cookies upang mapeke ang isang kahilingan ng user. Sa isip, dapat gumamit ng bagong identifier para sa bawat kahilingan, na magpapaliit sa posibilidad ng paggamit ng session ng ibang tao. Ngunit isasaalang-alang namin ang pangkalahatang kaso kapag ang oras ng pagbabagong-buhay ng session identifier ay arbitraryong itinakda.

(Aalisin namin ang bahagi ng code na napag-usapan na).

Function startSession($isUserActivity=true) ( ​​​​ // Session identifier lifetime $idLifetime = 60; ... if ($idLifetime) ( // Kung nakatakda ang session identifier lifetime, // suriin ang oras na lumipas mula noong session ay ginawa o ang huling pagbabagong-buhay // (oras ng huling kahilingan kung kailan na-update ang variable ng session ng pagsisimula) if (isset($_SESSION["starttime"])) ( if ($t-$_SESSION["starttime"] >= $ idLifetime) ( // Oras na nag-expire ang buhay ng session identifier // Bumuo ng bagong identifier session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( // Nakarating kami dito kung katatapos lang ng session ginawa // Itakda ang oras para sa pagbuo ng session identifier sa kasalukuyang oras $_SESSION["starttime"] = $t; ) ) return true; )

Kaya, kapag gumagawa ng bagong session (na nangyayari kapag matagumpay na nag-log in ang user), itinakda namin ang variable na oras ng pagsisimula ng session, na nag-iimbak para sa amin ng oras ng huling henerasyon ng session identifier, sa isang halaga na katumbas ng kasalukuyang oras ng server. Susunod, sa bawat kahilingan, tinitingnan namin kung sapat na oras (idLifetime) ang lumipas mula noong huling henerasyon ng identifier, at kung gayon, bumubuo kami ng bago. Kaya, kung sa panahon ng itinakdang buhay ng identifier ang attacker na nakatanggap ng cookie ng awtorisadong user ay walang oras na gamitin ito, ang pekeng kahilingan ay ituring ng server bilang hindi awtorisado, at ang attacker ay dadalhin sa login page .

Tandaan: Napupunta ang bagong session ID sa cookie ng browser kapag tinawag ang session_regenerate_id() function, na nagpapadala ng bagong cookie, katulad ng session_start() function, kaya hindi namin kailangang i-update ang cookie mismo.

Kung gusto naming gawing secure ang aming mga session hangga't maaari, sapat na upang itakda ang buhay ng identifier sa isa o kahit na alisin ang session_regenerate_id() function mula sa mga bracket at alisin ang lahat ng mga tseke, na hahantong sa pagbabagong-buhay ng identifier sa bawat isa. hiling. (Hindi ko pa nasubok ang epekto ng diskarteng ito sa pagganap, at masasabi ko lang na ang session_regenerate_id(true) function ay mahalagang gumaganap lamang ng 4 na pagkilos: pagbuo ng bagong identifier, paggawa ng header na may session cookie, pagtanggal ng luma at paggawa isang bagong session file).

Lyrical digression: Kung ang Trojan ay lumabas na napakatalino na hindi ito nagpapadala ng cookies sa umaatake, ngunit inaayos kaagad ang pagpapadala ng isang paunang inihanda na pekeng kahilingan sa sandaling matanggap ang cookie, ang paraan na inilarawan sa itaas ay malamang na hindi magagawang protektahan laban sa gayong pag-atake, dahil sa pagitan ng oras na natanggap ng Trojan ang cookie at pagpapadala ng isang pekeng kahilingan ay halos walang pagkakaiba, at may mataas na posibilidad na sa sandaling ito ang session identifier ay hindi muling mabubuo.

Posibilidad ng sabay-sabay na trabaho sa isang browser sa ngalan ng ilang user Ang huling gawain na gusto kong isaalang-alang ay ang posibilidad ng sabay-sabay na trabaho sa isang browser ng ilang user. Ang tampok na ito ay lalong kapaki-pakinabang sa yugto ng pagsubok, kapag kailangan mong tularan ang sabay-sabay na gawain ng mga gumagamit, at ipinapayong gawin ito sa iyong paboritong browser, sa halip na gamitin ang buong magagamit na arsenal o pagbubukas ng ilang mga pagkakataon ng browser sa mode na incognito .

Sa aming mga nakaraang halimbawa, hindi namin tahasang tinukoy ang pangalan ng session, kaya ginamit ang default na pangalan ng PHP (PHPSESSID). Nangangahulugan ito na ang lahat ng mga session na ginawa namin sa ngayon ay nagpadala ng cookie sa browser sa ilalim ng pangalang PHPSESSID. Malinaw, kung ang pangalan ng cookie ay palaging pareho, kung gayon walang paraan upang ayusin ang dalawang session na may parehong pangalan sa loob ng parehong browser. Ngunit kung ginamit namin ang aming sariling pangalan ng session para sa bawat user, malulutas ang problema. Gawin natin ito.

Function startSession($isUserActivity=true, $prefix=null) ( ... if (session_id()) return true; // Kung ang prefix ng user ay ipinasa sa mga parameter, // magtakda ng natatanging pangalan ng session na kinabibilangan nito prefix, // kung hindi man ay itakda ang karaniwang pangalan para sa lahat ng user (halimbawa, MYPROJECT) session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); kung (! session_start()) return false; ... )

Ngayon ang natitira na lang ay tiyakin na ang script ng pagtawag ay nagpapasa ng isang natatanging prefix para sa bawat user sa startSession() function. Magagawa ito, halimbawa, sa pamamagitan ng pagpasa ng prefix sa GET/POST na mga parameter ng bawat kahilingan o sa pamamagitan ng karagdagang cookie.

Konklusyon Sa konklusyon, ibibigay ko ang kumpletong panghuling code ng aming mga function para sa pagtatrabaho sa mga session ng PHP, kasama ang lahat ng mga gawaing tinalakay sa itaas.

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

Umaasa ako na ang artikulong ito ay makatipid ng ilang oras para sa mga hindi pa masyadong malalim na nagsaliksik sa mekanismo ng session, at magbigay ng sapat na pananaw sa mekanismong ito para sa mga nagsisimula pa lamang na pamilyar sa PHP.

Kailangan mo ba ng username at password?

Upang magsumite ng mga artikulo online at suriin ang katayuan ng mga isinumiteng artikulo, kailangan mong magparehistro at mag-log in sa iyong account.

Checklist para sa paghahanda ng isang artikulo para sa pagsusumite

Bilang bahagi ng proseso ng pagsusumite ng artikulo, dapat suriin ng mga may-akda na natutugunan ng kanilang artikulo ang lahat ng sumusunod na punto; maaaring ibalik ang mga artikulo sa mga may-akda kung hindi nila natutugunan ang mga kinakailangang ito.

Ang artikulo ay inihanda alinsunod sa mga kinakailangan

Mga tuntunin ng paglilipat ng copyright

Pinapanatili ng mga may-akda ang copyright ng akda at binibigyan ang journal ng mga karapatan sa paglalathala sa unang pagkakataon kasama ng gawa, habang nililisensyahan ito sa ilalim ng mga tuntunin ng Creative Commons Attribution License, na nagpapahintulot sa iba na ipamahagi ang gawaing ito nang may mandatoryong pagpapatungkol sa may-akda ng gawa at isang link sa orihinal na publikasyon sa journal na ito.

Pribadong pahayag

Ang mga pangalan at email address na ipinasok sa website ng magazine na ito ay gagamitin lamang para sa mga layuning itinalaga ng magazine na ito at hindi gagamitin para sa anumang iba pang layunin o ibibigay sa sinumang ibang tao o entity.

Bago magrehistro sa system, sumasang-ayon ang user sa patakaran para sa pagproseso at pag-iimbak ng personal na data.

Mga Pagbabayad ng May-akda

1500 character na may mga puwang: 300.00 (RUB)

Paglalathala ng 1 pahina ng manuskrito (1500 character) - 300 rubles. Ang mga graphic na materyales / talahanayan ay binabayaran nang hiwalay - 50 rubles / 1 piraso. Ang kopya ng may-akda, kabilang ang pagpapadala sa loob ng Russia, ay binabayaran sa kahilingan ng may-akda - 400 rubles. Pagpapadala sa ibang bansa - 800 rubles. Ang halaga ng pagpapadala ng isang sertipiko ng pagtanggap ng materyal para sa publikasyon ay 150 rubles.

Pagsasalin ng kasamang impormasyon (buong pangalan, lugar ng trabaho ng mga may-akda; pamagat; abstract; mga keyword) sa Ingles 0.5 rubles para sa bawat karakter, kabilang ang mga puwang.

Pansin! Ang mga may-akda (kandidato at doktor ng agham) na, ayon sa elibrary.ru, ay mayroong 300 o higit pang mga pagsipi (ang bahagi ng sariling pagsipi ay dapat na hindi hihigit sa 30%) ay nai-publish nang walang bayad. Kung karapat-dapat ka para sa libreng publikasyon, kapag nagsusumite ng materyal, sa field ng mga komento, ipahiwatig ang isang link sa iyong elibrary profile na may bilang ng mga pagsipi. Ang mga gastos sa pagpapadala para sa koleksyon ay binabayaran nang hiwalay.

Ang seguridad ng website ay batay sa pamamahala ng session. Kapag kumonekta ang isang user sa isang secure na site, nagbibigay sila ng mga kredensyal, kadalasan sa anyo ng isang username at password. Walang ideya ang web server kung sinong user ang naka-log in na o kung paano sila nag-navigate mula sa pahina patungo sa pahina. Pinipigilan ng mekanismo ng session ang mga user na maglagay ng password sa tuwing gusto nilang magsagawa ng bagong aksyon o pumunta sa isang bagong page.

Sa pangkalahatan, tinitiyak ng pamamahala ng session na ang kasalukuyang nakakonektang user ay ang na-authenticate. Ngunit sa kasamaang-palad, ang mga session ay naging isang halatang target para sa mga hacker dahil maaari nilang payagan ang pag-access sa isang web server nang hindi nangangailangan ng pagpapatunay.

Pagkatapos ma-authenticate ang user, binibigyan siya ng web server ng session ID. Ang ID na ito ay nakaimbak sa browser at pinapalitan sa tuwing kailangan ang pagpapatunay. Binibigyang-daan ka nitong maiwasan ang paulit-ulit na proseso ng pag-login/pagpasok ng password. Ang lahat ng ito ay nangyayari sa background at hindi nagiging sanhi ng kakulangan sa ginhawa sa gumagamit. Isipin kung ipinasok mo ang iyong username at password sa tuwing titingin ka ng bagong page!

Sa artikulong ito susubukan kong balangkasin ang lahat ng mga paraan na alam kong protektahan ang session ID sa PHP.

Paggamit ng cookies Bilang default, ang lahat ng impormasyon ng session, kabilang ang ID, ay ipinapadala sa isang cookie. Ngunit hindi ito palaging nangyayari. Ang ilang mga gumagamit ay hindi pinagana ang cookies sa kanilang mga browser. Sa kasong ito, ipapasa ng browser ang session ID sa URL.

Dito ipinapadala ang ID sa malinaw na text, kumpara sa isang session sa pamamagitan ng cookie, kapag nakatago ang impormasyon sa header ng HTTP. Ang pinakasimpleng paraan upang maprotektahan laban dito ay ang pagbabawal sa pagpapadala ng session identifier sa pamamagitan ng address bar. Magagawa ito sa pamamagitan ng pagsulat ng sumusunod sa Apache server .htaccess configuration file:

Php_flag session.use_only_cookies on

Paggamit ng Encryption Kung ang iyong site ay kailangang magproseso ng sensitibong impormasyon, gaya ng mga numero ng credit card (hello mula sa Sony), dapat mong gamitin ang SSL3.0 o TSL1.0 encryption. Upang gawin ito, kapag nagtatakda ng cookie, dapat mong tukuyin ang true para sa secure na parameter.

Kung iimbak mo ang password ng session sa variable na $_SESSION (mas mainam pa ring gumamit ng sql), hindi mo ito dapat iimbak sa malinaw na text.

Kung ($_SESSION["password"] == $userpass) ( // code )

Hindi secure ang code sa itaas dahil naka-store ang password bilang plain text sa isang variable ng session. Sa halip, gumamit ng md5 encryption, tulad nito:

Kung ($_SESSION["md5password"] == md5($userpass)) ( // code )

Pagsusuri ng browser Upang maiwasan ang posibilidad ng paggamit ng session mula sa isa pang browser (computer), dapat kang magpasok ng check ng field ng header ng user-agent na HTTP:

Session_start(); kung (isset($_SESSION["HTTP_USER_AGENT"])) ( kung ($_SESSION["HTTP_USER_AGENT"] != md5($_SERVER["HTTP_USER_AGENT"])) ( // code ) ) iba pa ( $_SESSION["HTTP_USER_AGENT" ] = md5($_SERVER["HTTP_USER_AGENT"]); )

Pag-expire ng session Limitahan ang buhay ng session, pati na rin ang oras ng pag-expire ng cookies. Bilang default, ang tagal ng session ay 1440 segundo. Maaari mong baguhin ang halagang ito sa pamamagitan ng php.ini at .htaccess. Halimbawa para sa .htaccess:

# Habambuhay ng session sa ilang segundo
php_value session.gc_maxlifetime 3600
# Habambuhay ng cookie sa ilang segundo
php_value session.cookie_lifetime 3600

Pagbubuklod sa pamamagitan ng IP address Sa ilang mga sitwasyon (hindi palaging), dapat kang magbigkis sa pamamagitan ng IP address. Pangunahin kapag limitado ang bilang ng mga user at may mga static na IP. Ang tseke ay maaaring batay sa listahan ng mga pinapayagang IP address,

Isama ang("ip_list.php"); //$ip_white_list = array ("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 "ACCESS DENY!"; )

O sa pamamagitan ng IP address para sa bawat kahilingan (para lamang sa static na IP):

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

Dapat mong malaman na ang pag-hack ay hindi ganap na maiiwasan. Maaari mo lamang gawin ang hack na ito bilang mahirap hangga't maaari sa pamamagitan ng anumang alam na paraan. Gayunpaman, hindi mo rin dapat kalimutan ang tungkol sa iyong mga legal na gumagamit, upang hindi kumplikado ang kanilang buhay sa naturang proteksyon.

Ang artikulong ito ay isinulat noong 2009 at nananatiling isa sa aming pinakasikat na mga post. Kung gusto mong matuto nang higit pa tungkol sa PHP at MySQL, maaari mong makita ito ng mahusay na interes.

TANDAAN: Ang artikulong ito ay bagong na-update upang gumana sa PHP 4.2 o mas bago!

Kamakailan, nagkaroon ako ng pagkakataon na gumawa ng isang maliit na proyekto kasama ang isang grupo ng mga tao. Napagpasyahan namin nang maaga sa email na iyon lamang ay hindi magiging sapat upang panatilihin ang lahat sa loop, kaya ako ay naatasang gumawa ng isang maliit na Web site para sa proyekto. Maglalaman ito ng isang simpleng message board, isang lugar kung saan maaari kaming mag-upload ng mga dokumento at iba pang mga file para magamit ng natitirang bahagi ng koponan, at impormasyon sa pakikipag-ugnayan para sa iba't ibang miyembro ng koponan.

Para gumana ang marami sa mga feature na ito, alam kong kailangan kong mag-log in ang mga user bago i-access ang mga nauugnay na bahagi ng site. Ang kailangan ko ay isang sistema na hahayaan ang mga user na magparehistro para sa isang user ID upang ma-access ang site, pagkatapos ay agad na gamitin ang ID na iyon nang walang anumang interbensyon sa aking bahagi.

Sa artikulong ito, magbibigay ako ng pangkalahatang-ideya ng system na aking binuo, simula sa unang kalahati ng proseso ng pag-signup ng user. Sa ikalawang kalahati, tututukan ko ang mismong site, kung paano ito nangangailangan ng mga user na mag-log in at pagkatapos ay panatilihin ang status na naka-log in sa kabuuan ng kanilang pagbisita. Bibigyan ko ng espesyal na pansin ang paggamit ng mga tampok sa pamamahala ng session sa PHP. Sa pagtatapos, dapat mayroon ka ng lahat ng impormasyong kailangan mo upang ipatupad ang isang katulad na sistema ng iyong sarili.

Sa buong artikulong ito, ipagpapalagay ko na mayroon kang pangunahing kaalaman sa wikang PHP, ang paggamit ng mga form upang magsumite ng impormasyon sa isang script ng PHP, at kung paano maaaring gamitin ang PHP upang makipag-ugnayan sa isang database ng MySQL. Kung ang alinman sa mga ito ay mga banyagang konsepto sa iyo, dapat mong simulan sa pamamagitan ng pagbabasa ng aking nakaraang artikulo, .

Unang Bahagi: Ang Proseso ng Pag-signup Ang Form ng Pag-signup

Ang isang natural na lugar upang simulan ang pagbuo ng isang site na mangangailangan ng mga user na magparehistro para sa pag-access ay ang proseso ng pagpaparehistro mismo. Tulad ng inaasahan ng isa, ang isang simpleng Web-based na form ay gagawa ng lansihin. Narito ang magiging hitsura nito:

At narito ang code para sa form na ito:




Bagong Pagpaparehistro ng User



Bagong Form ng Pagpaparehistro ng User

* nagsasaad ng kinakailangang field


Dahil malinaw na ang layunin, ituturo ko sa iyo ang code para sa accesscontrol.php . Magsimula sa pamamagitan ng pagsasama ng iyong dalawang madaling gamiting isama ang mga file: