PHP में सत्र आईडी सुरक्षा। PHP में सत्रों का उपयोग करने के नुकसान PHP सत्र का उपयोग करके किसी मान या सरणी को पास करना

नमस्कार, प्रिय समुदाय।

सबसे पहले, मैं आपको एक अत्यंत उपयोगी संसाधन के लिए धन्यवाद देना चाहता हूँ। एक से अधिक बार मुझे यहां कई दिलचस्प विचार और व्यावहारिक सलाह मिली हैं।

इस लेख का उद्देश्य PHP में सत्रों का उपयोग करने के नुकसान को उजागर करना है। बेशक, PHP दस्तावेज़ीकरण और बहुत सारे उदाहरण हैं, और इस लेख का उद्देश्य संपूर्ण मार्गदर्शिका होना नहीं है। इसे सत्रों के साथ काम करने की कुछ बारीकियों को प्रकट करने और डेवलपर्स को समय की अनावश्यक बर्बादी से बचाने के लिए डिज़ाइन किया गया है।

सत्रों का उपयोग करने का सबसे आम उदाहरण, निश्चित रूप से, उपयोगकर्ता प्राधिकरण है। आइए सबसे बुनियादी कार्यान्वयन से शुरुआत करें ताकि नए कार्य सामने आने पर इसे धीरे-धीरे विकसित किया जा सके।

(स्थान और समय बचाने के लिए, हम यहां एक सुंदर वर्ग पदानुक्रम, व्यापक त्रुटि प्रबंधन और अन्य अच्छी सामग्री के साथ एक पूर्ण परीक्षण एप्लिकेशन बनाने के बजाय, अपने उदाहरणों को केवल सत्र कार्यों तक ही सीमित रखेंगे)।

फ़ंक्शन प्रारंभ सत्र() ( // यदि सत्र पहले ही शुरू हो चुका है, तो निष्पादन बंद करें और TRUE // लौटाएं (php.ini सेटिंग्स फ़ाइल में session.auto_start पैरामीटर अक्षम होना चाहिए - डिफ़ॉल्ट मान) यदि (session_id()) वापस लौटें सही; अन्यथा session_start() लौटाएं; // नोट: संस्करण 5.3.0 से पहले, session_start() फ़ंक्शन कोई त्रुटि होने पर भी TRUE लौटाता था। // यदि आप 5.3.0 से पहले के संस्करण का उपयोग कर रहे हैं, तो एक अतिरिक्त जांच करें session_id() के लिए // session_start() को कॉल करने के बाद) फ़ंक्शन नष्ट सत्र() (यदि (session_id()) ( // यदि कोई सक्रिय सत्र है, तो सत्र कुकीज़ हटाएं, setcookie(session_name(), session_id(), time( )-60*60*24); // और सत्र को नष्ट करें session_unset( ); session_destroy(); ) )

नोट: यह माना जाता है कि पाठक को PHP सत्रों का बुनियादी ज्ञान है, इसलिए हम यहां session_start() और session_destroy() फ़ंक्शन के संचालन के सिद्धांत को कवर नहीं करेंगे। लॉगिन फॉर्म के लेआउट और उपयोगकर्ता प्रमाणीकरण के कार्य लेख के विषय से संबंधित नहीं हैं, इसलिए हम उन्हें भी छोड़ देंगे। मैं आपको केवल यह याद दिला दूं कि प्रत्येक आगामी अनुरोध में उपयोगकर्ता की पहचान करने के लिए, सफल लॉगिन के समय, हमें उपयोगकर्ता पहचानकर्ता को एक सत्र चर (उदाहरण के लिए उपयोगकर्ता आईडी नाम दिया गया) में संग्रहीत करने की आवश्यकता है, जो बाद के सभी अनुरोधों में उपलब्ध होगा सत्र का जीवन. हमारे स्टार्टसेशन() फ़ंक्शन के परिणाम को संसाधित करना भी आवश्यक है। यदि फ़ंक्शन FALSE लौटाता है, तो ब्राउज़र में लॉगिन फ़ॉर्म प्रदर्शित करें। यदि फ़ंक्शन TRUE लौटाता है, और अधिकृत उपयोगकर्ता (हमारे मामले में - उपयोगकर्ता आईडी) के पहचानकर्ता वाला एक सत्र चर मौजूद है - अधिकृत उपयोगकर्ता का पृष्ठ प्रदर्शित करें (त्रुटि प्रबंधन के बारे में अधिक जानकारी के लिए, अतिरिक्त दिनांक 2013-06 देखें- सत्र चर पर अनुभाग में 07)।

अभी तक सब कुछ स्पष्ट है. प्रश्न तब शुरू होते हैं जब आपको उपयोगकर्ता निष्क्रियता नियंत्रण (सत्र समयबाह्य) लागू करने की आवश्यकता होती है, एकाधिक उपयोगकर्ताओं को एक ब्राउज़र में एक साथ काम करने में सक्षम बनाता है, और सत्रों को अनधिकृत उपयोग से भी बचाता है। इस पर नीचे चर्चा की जाएगी।

अंतर्निहित PHP टूल का उपयोग करके उपयोगकर्ता की निष्क्रियता को नियंत्रित करना पहला प्रश्न जो अक्सर उपयोगकर्ताओं के लिए विभिन्न कंसोल के डेवलपर्स के बीच उठता है, वह उपयोगकर्ता की ओर से निष्क्रियता की स्थिति में सत्र की स्वचालित समाप्ति है। PHP की अंतर्निहित क्षमताओं का उपयोग करके ऐसा करने से आसान कुछ भी नहीं है। (यह विकल्प विशेष रूप से विश्वसनीय या लचीला नहीं है, लेकिन पूर्णता के लिए हम इस पर विचार करेंगे)।

फ़ंक्शन प्रारंभ सत्र() (//उपयोगकर्ता निष्क्रियता समयबाह्य (सेकंड में) $sessionLifetime = 300; यदि (session_id()) सत्य लौटाता है; // कुकी जीवनकाल सेट करें ini_set('session.cookie_lifetime', $sessionLifetime); // यदि उपयोगकर्ता निष्क्रियता टाइमआउट सेट है, सर्वर पर सत्र जीवनकाल सेट करें // नोट: एक उत्पादन सर्वर के लिए, इन मापदंडों को php.ini फ़ाइल में पूर्व निर्धारित करने की अनुशंसा की जाती है यदि ($sessionLifetime) ini_set('session.gc_maxlifetime', $sessionLifetime) ; यदि (session_start()) ( setcookie(session_name(), session_id(), time()+$sessionLifetime); सही लौटें; ) अन्यथा गलत लौटें; )

कुछ स्पष्टीकरण. जैसा कि आप जानते हैं, PHP यह निर्धारित करता है कि अनुरोध हेडर में ब्राउज़र द्वारा भेजे गए कुकी नाम से किस सत्र को लॉन्च करने की आवश्यकता है। बदले में, ब्राउज़र इस कुकी को सर्वर से प्राप्त करता है, जहां session_start() फ़ंक्शन इसे रखता है। यदि ब्राउज़र कुकी समाप्त हो गई है, तो इसे अनुरोध में नहीं भेजा जाएगा, जिसका अर्थ है कि PHP यह निर्धारित नहीं कर पाएगा कि कौन सा सत्र शुरू करना है और इसे एक नया सत्र बनाने के रूप में माना जाएगा। PHP सेटिंग्स पैरामीटर session.gc_maxlifetime, जो हमारे उपयोगकर्ता निष्क्रियता टाइमआउट के बराबर सेट है, PHP सत्र का जीवनकाल निर्धारित करता है और सर्वर द्वारा नियंत्रित किया जाता है। सत्र जीवनकाल को नियंत्रित करना निम्नानुसार काम करता है (यहां हम PHP में सबसे आम और डिफ़ॉल्ट विकल्प के रूप में अस्थायी फ़ाइलों में सत्र संग्रहीत करने का एक उदाहरण मानते हैं)।

जब एक नया सत्र बनाया जाता है, तो PHP सेटिंग्स पैरामीटर session.save_path में सत्र संग्रहीत करने के लिए निर्देशिका के रूप में सेट की गई निर्देशिका में sess_ नामक एक फ़ाइल बनाई जाती है, जहां सत्र पहचानकर्ता होता है। इसके बाद, प्रत्येक अनुरोध में, पहले से मौजूद सत्र को लॉन्च करने के समय, PHP इस फ़ाइल के संशोधन समय को अपडेट करता है। इस प्रकार, प्रत्येक बाद के अनुरोध में, PHP, वर्तमान समय और सत्र फ़ाइल के अंतिम संशोधन के समय के बीच के अंतर से, यह निर्धारित कर सकता है कि सत्र सक्रिय है या उसका जीवनकाल पहले ही समाप्त हो चुका है। (पुरानी सत्र फ़ाइलों को हटाने की प्रक्रिया पर अगले भाग में अधिक विस्तार से चर्चा की गई है।)

नोट: यहां यह ध्यान दिया जाना चाहिए कि session.gc_maxlifetime पैरामीटर एक सर्वर के भीतर सभी सत्रों पर लागू होता है (अधिक सटीक रूप से, एक मुख्य PHP प्रक्रिया के भीतर)। व्यवहार में, इसका मतलब यह है कि यदि सर्वर पर कई साइटें चल रही हैं, और उनमें से प्रत्येक का अपना उपयोगकर्ता निष्क्रियता टाइमआउट है, तो किसी एक साइट पर इस पैरामीटर को सेट करने से अन्य साइटों के लिए इसकी सेटिंग हो जाएगी। यही बात साझा होस्टिंग पर भी लागू होती है। इस स्थिति से बचने के लिए, एक ही सर्वर के भीतर प्रत्येक साइट के लिए अलग-अलग सत्र निर्देशिकाओं का उपयोग किया जाता है। सत्र निर्देशिका के लिए पथ सेट करना php.ini सेटिंग्स फ़ाइल में session.save_path पैरामीटर का उपयोग करके या ini_set() फ़ंक्शन को कॉल करके किया जाता है। इसके बाद, प्रत्येक साइट के सत्र अलग-अलग निर्देशिकाओं में संग्रहीत किए जाएंगे, और किसी एक साइट पर सेट किया गया session.gc_maxlifetime पैरामीटर केवल उसके सत्र के लिए मान्य होगा। हम इस मामले पर विस्तार से विचार नहीं करेंगे, खासकर जब से हमारे पास उपयोगकर्ता निष्क्रियता की निगरानी के लिए अधिक लचीला विकल्प है।

सत्र चर का उपयोग करके उपयोगकर्ता निष्क्रियता को नियंत्रित करना ऐसा प्रतीत होता है कि पिछला विकल्प, अपनी सभी सादगी (कोड की केवल कुछ अतिरिक्त पंक्तियों) के लिए, वह सब कुछ देता है जो हमें चाहिए। लेकिन क्या होगा यदि प्रत्येक अनुरोध को उपयोगकर्ता गतिविधि का परिणाम नहीं माना जा सकता है? उदाहरण के लिए, एक पेज में एक टाइमर होता है जो समय-समय पर सर्वर से अपडेट प्राप्त करने के लिए AJAX अनुरोध करता है। इस तरह के अनुरोध को उपयोगकर्ता गतिविधि के रूप में नहीं माना जा सकता है, जिसका अर्थ है कि इस मामले में सत्र जीवनकाल को स्वचालित रूप से बढ़ाना सही नहीं है। लेकिन हम जानते हैं कि PHP हर बार session_start() फ़ंक्शन को कॉल करने पर सत्र फ़ाइल के संशोधन समय को स्वचालित रूप से अपडेट करता है, जिसका अर्थ है कि किसी भी अनुरोध से सत्र जीवनकाल का विस्तार हो जाएगा, और उपयोगकर्ता निष्क्रियता टाइमआउट कभी नहीं होगा। इसके अलावा, session.gc_maxlifetime पैरामीटर की पेचीदगियों के बारे में पिछले अनुभाग का अंतिम नोट कुछ लोगों के लिए बहुत भ्रमित करने वाला और लागू करने में कठिन लग सकता है।

इस समस्या को हल करने के लिए, हम अंतर्निहित PHP तंत्रों का उपयोग छोड़ देंगे और कई नए सत्र चर पेश करेंगे जो हमें उपयोगकर्ता निष्क्रियता के समय को स्वयं नियंत्रित करने की अनुमति देंगे।

फ़ंक्शन प्रारंभ सत्र ($isUserActivity=true) ($sessionLifetime = 300; यदि (session_id()) सही लौटाता है; // ब्राउज़र बंद करने से पहले कुकी जीवनकाल सेट करें (हम सर्वर साइड पर सब कुछ नियंत्रित करेंगे) ini_set('session. कुकी_लाइफटाइम", 0); अगर (! सेशन_स्टार्ट()) गलत लौटाता है; $t = समय(); अगर ($सेशनलाइफटाइम) ( // यदि उपयोगकर्ता निष्क्रियता टाइमआउट सेट है, // अंतिम उपयोगकर्ता गतिविधि के बाद बीता हुआ समय जांचें // (अंतिम अनुरोध समय जब अंतिम गतिविधि सत्र चर अद्यतन किया गया था) यदि (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // यदि समय बीत चुका है उपयोगकर्ता की अंतिम गतिविधि, // निष्क्रियता टाइमआउट से अधिक है, जिसका अर्थ है कि सत्र समाप्त हो गया है और आपको सत्र को नष्ट करने की आवश्यकता है (); गलत लौटें; ) अन्यथा ( // यदि टाइमआउट अभी तक नहीं हुआ है, // और यदि अनुरोध उपयोगकर्ता गतिविधि के परिणामस्वरूप आया है, // अंतिम गतिविधि चर को वर्तमान एक बार के मूल्य के साथ अपडेट करें, // जिससे सत्र समय को दूसरे सत्र लाइफटाइम सेकंड तक बढ़ाया जा सकता है यदि ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) सच लौटें; )

आइए संक्षेप करें. प्रत्येक अनुरोध में, हम जांचते हैं कि क्या अंतिम उपयोगकर्ता गतिविधि के बाद से वर्तमान क्षण तक टाइमआउट पहुंच गया है, और यदि यह पहुंच गया है, तो हम सत्र को नष्ट कर देते हैं और फ़ंक्शन के निष्पादन को बाधित करते हैं, FALSE लौटाते हैं। यदि समय समाप्त नहीं हुआ है, और $isUserActivity पैरामीटर TRUE मान के साथ फ़ंक्शन को पास कर दिया गया है, तो हम उपयोगकर्ता की अंतिम गतिविधि का समय अपडेट करते हैं। हमें बस कॉलिंग स्क्रिप्ट में यह निर्धारित करना है कि क्या अनुरोध उपयोगकर्ता गतिविधि का परिणाम है, और यदि नहीं, तो $isUserActivity पैरामीटर को FALSE पर सेट करके स्टार्टसेशन फ़ंक्शन को कॉल करें।

2013-06-07 से सेशनस्टार्ट() फ़ंक्शन के परिणाम को संसाधित करना

टिप्पणियों में बताया गया कि FALSE लौटाने से त्रुटि के कारण की पूरी समझ नहीं मिलती है, और यह बिल्कुल उचित है। मैंने यहां विस्तृत त्रुटि प्रबंधन प्रकाशित नहीं किया है (लेख की लंबाई पहले से ही काफी बड़ी है), क्योंकि यह सीधे लेख के विषय से संबंधित नहीं है। लेकिन टिप्पणियों को देखते हुए, मैं स्पष्ट कर दूंगा।

जैसा कि आप देख सकते हैं, सेशनस्टार्ट फ़ंक्शन दो मामलों में FALSE लौटा सकता है। या तो कुछ आंतरिक सर्वर त्रुटियों (उदाहरण के लिए, php.ini में गलत सत्र सेटिंग्स) के कारण सत्र शुरू नहीं किया जा सका, या सत्र जीवनकाल समाप्त हो गया है। पहले मामले में, हमें उपयोगकर्ता को एक त्रुटि वाले पृष्ठ पर रीडायरेक्ट करना होगा जिसमें कहा गया हो कि सर्वर पर समस्याएं हैं और समर्थन से संपर्क करने के लिए एक फॉर्म है। दूसरे मामले में, हमें उपयोगकर्ता को लॉगिन फॉर्म में स्थानांतरित करना होगा और उसमें एक संबंधित संदेश प्रदर्शित करना होगा जिसमें कहा गया हो कि सत्र समाप्त हो गया है। ऐसा करने के लिए, हमें त्रुटि कोड दर्ज करने और FALSE के बजाय संबंधित कोड वापस करने की आवश्यकता है, और कॉलिंग विधि में, इसकी जांच करें और तदनुसार कार्य करें।

अब, भले ही सर्वर पर कोई सत्र अभी भी मौजूद है, यदि उपयोगकर्ता की निष्क्रियता का समय समाप्त हो गया है तो इसे पहली बार एक्सेस करते समय नष्ट कर दिया जाएगा। और यह इस बात की परवाह किए बिना होगा कि वैश्विक PHP सेटिंग्स में कौन सा सत्र जीवनकाल निर्धारित किया गया है।

नोट: यदि ब्राउज़र बंद हो गया और सत्र नाम कुकी स्वचालित रूप से नष्ट हो गई तो क्या होगा? अगली बार जब ब्राउज़र खोला जाएगा तो सर्वर से किए गए अनुरोध में सत्र कुकी नहीं होगी, और सर्वर सत्र को खोलने और उपयोगकर्ता की निष्क्रियता टाइमआउट की जांच करने में सक्षम नहीं होगा। हमारे लिए, यह एक नया सत्र बनाने के बराबर है और किसी भी तरह से कार्यक्षमता या सुरक्षा को प्रभावित नहीं करता है। लेकिन एक वाजिब सवाल उठता है - पुराने सत्र को कौन नष्ट करेगा, अगर अब तक हमने समय समाप्त होने के बाद इसे नष्ट कर दिया है? या क्या यह अब सत्र निर्देशिका में हमेशा के लिए लटका रहेगा? PHP में पुराने सत्रों को साफ़ करने के लिए, कचरा संग्रहण नामक एक तंत्र है। यह सर्वर पर अगले अनुरोध के समय चलता है और सत्र फ़ाइलों की अंतिम संशोधन तिथि के आधार पर सभी पुराने सत्रों को साफ़ कर देता है। लेकिन कचरा संग्रहण तंत्र सर्वर के प्रत्येक अनुरोध के साथ प्रारंभ नहीं होता है। लॉन्चिंग की आवृत्ति (या बल्कि, संभावना) दो सेटिंग्स पैरामीटर session.gc_probability और session.gc_divisor द्वारा निर्धारित की जाती है। पहले पैरामीटर को दूसरे से विभाजित करने का परिणाम कचरा संग्रहण तंत्र लॉन्च करने की संभावना है। इस प्रकार, सर्वर पर प्रत्येक अनुरोध के साथ सत्र समाशोधन तंत्र शुरू करने के लिए, इन मापदंडों को समान मानों पर सेट किया जाना चाहिए, उदाहरण के लिए "1"। यह दृष्टिकोण एक स्वच्छ सत्र निर्देशिका की गारंटी देता है, लेकिन सर्वर के लिए स्पष्ट रूप से बहुत महंगा है। इसलिए, उत्पादन प्रणालियों पर, session.gc_divisor का डिफ़ॉल्ट मान 1000 पर सेट है, जिसका अर्थ है कि कचरा संग्रहण तंत्र 1/1000 की संभावना के साथ चलेगा। यदि आप अपनी php.ini फ़ाइल में इन सेटिंग्स के साथ प्रयोग करते हैं, तो आप देख सकते हैं कि ऊपर वर्णित मामले में, जब ब्राउज़र बंद हो जाता है और अपनी सभी कुकीज़ साफ़ कर देता है, तब भी कुछ समय के लिए सत्र निर्देशिका में पुराने सत्र बचे रहते हैं। लेकिन इससे आपको चिंतित नहीं होना चाहिए, क्योंकि... जैसा कि पहले ही कहा गया है, यह किसी भी तरह से हमारे तंत्र की सुरक्षा को प्रभावित नहीं करता है।

2013-06-07 से अद्यतन सत्र फ़ाइल लॉकिंग के कारण स्क्रिप्ट को फ़्रीज़ होने से रोकना

टिप्पणियों में सत्र फ़ाइल अवरुद्ध होने के कारण एक साथ चल रही स्क्रिप्ट के फ़्रीज़ होने का मुद्दा उठाया गया (सबसे महत्वपूर्ण विकल्प लॉन्ग पोल है)।

आरंभ करने के लिए, मैं ध्यान देता हूं कि यह समस्या सीधे सर्वर लोड या उपयोगकर्ताओं की संख्या पर निर्भर नहीं करती है। बेशक, जितने अधिक अनुरोध होंगे, स्क्रिप्ट उतनी ही धीमी गति से निष्पादित होंगी। लेकिन यह अप्रत्यक्ष निर्भरता है. समस्या केवल एक सत्र के भीतर ही प्रकट होती है, जब सर्वर को एक उपयोगकर्ता की ओर से कई अनुरोध प्राप्त होते हैं (उदाहरण के लिए, उनमें से एक लंबा मतदान है, और बाकी नियमित अनुरोध हैं)। प्रत्येक अनुरोध उसी सत्र फ़ाइल तक पहुंचने का प्रयास करता है, और यदि पिछले अनुरोध ने फ़ाइल को अनलॉक नहीं किया है, तो अगला अनुरोध प्रतीक्षा में लटका रहेगा।

सत्र फ़ाइल लॉकिंग को न्यूनतम रखने के लिए, सत्र चर के साथ सभी क्रियाएं पूरी होने के तुरंत बाद session_write_close() फ़ंक्शन को कॉल करके सत्र को बंद करने की दृढ़ता से अनुशंसा की जाती है। व्यवहार में, इसका मतलब यह है कि आपको सत्र चर में सब कुछ संग्रहीत नहीं करना चाहिए और स्क्रिप्ट के निष्पादन के दौरान उन तक पहुंच नहीं बनानी चाहिए। और यदि आपको सत्र चर में कुछ कार्यशील डेटा संग्रहीत करने की आवश्यकता है, तो सत्र शुरू होने पर उन्हें तुरंत पढ़ें, बाद में उपयोग के लिए उन्हें स्थानीय चर में सहेजें और सत्र बंद करें (अर्थात् session_write_close फ़ंक्शन का उपयोग करके सत्र को बंद करना, और session_destroy का उपयोग करके इसे नष्ट नहीं करना ).

हमारे उदाहरण में, इसका मतलब है कि एक सत्र खोलने के तुरंत बाद, उसके जीवनकाल और एक अधिकृत उपयोगकर्ता के अस्तित्व की जांच करने के बाद, हमें एप्लिकेशन के लिए आवश्यक सभी अतिरिक्त सत्र चर को पढ़ना और सहेजना होगा (यदि कोई मौजूद है), फिर कॉल का उपयोग करके सत्र को बंद करें session_write_close() पर जाएं और स्क्रिप्ट का निष्पादन जारी रखें, चाहे वह लंबा मतदान हो या नियमित अनुरोध।

सत्रों को अनधिकृत उपयोग से बचाना आइए एक स्थिति की कल्पना करें। आपके उपयोगकर्ताओं में से एक को एक ट्रोजन मिलता है जो ब्राउज़र कुकीज़ (जिसमें हमारा सत्र संग्रहीत होता है) को लूटता है और इसे निर्दिष्ट ईमेल पर भेजता है। हमलावर कुकी प्राप्त करता है और इसका उपयोग हमारे अधिकृत उपयोगकर्ता की ओर से अनुरोध को धोखा देने के लिए करता है। सर्वर इस अनुरोध को सफलतापूर्वक स्वीकार करता है और संसाधित करता है जैसे कि यह किसी अधिकृत उपयोगकर्ता से आया हो। यदि आईपी पते का अतिरिक्त सत्यापन लागू नहीं किया जाता है, तो इस तरह के हमले से उपयोगकर्ता के खाते की सफल हैकिंग हो जाएगी, जिसके सभी आगामी परिणाम होंगे।

ऐसा क्यों संभव हुआ? जाहिर है, क्योंकि नाम और सत्र पहचानकर्ता हमेशा सत्र के पूरे जीवनकाल के लिए समान होते हैं, और यदि आपको यह डेटा प्राप्त होता है, तो आप आसानी से किसी अन्य उपयोगकर्ता की ओर से अनुरोध भेज सकते हैं (बेशक, इस सत्र के जीवनकाल के भीतर)। यह सबसे आम प्रकार का हमला नहीं हो सकता है, लेकिन सैद्धांतिक रूप से यह काफी संभव लगता है, खासकर यह देखते हुए कि ऐसे ट्रोजन को उपयोगकर्ता के ब्राउज़र कुकीज़ को लूटने के लिए व्यवस्थापक अधिकारों की भी आवश्यकता नहीं है।

आप इस प्रकार के हमलों से स्वयं को कैसे बचा सकते हैं? फिर, जाहिर है, सत्र पहचानकर्ता के जीवनकाल को सीमित करके और समय-समय पर उसी सत्र के भीतर पहचानकर्ता को बदलते हुए। हम पुराने सत्र को पूरी तरह से हटाकर और पुराने सत्र से सभी सत्र चर को कॉपी करके एक नया सत्र बनाकर सत्र का नाम भी बदल सकते हैं। लेकिन यह दृष्टिकोण के सार को प्रभावित नहीं करता है, इसलिए सरलता के लिए हम खुद को केवल सत्र पहचानकर्ता तक सीमित रखेंगे।

यह स्पष्ट है कि सत्र आईडी का जीवनकाल जितना छोटा होगा, किसी हमलावर को उपयोगकर्ता अनुरोध बनाने के लिए कुकीज़ प्राप्त करने और उनका उपयोग करने में उतना ही कम समय लगेगा। आदर्श रूप से, प्रत्येक अनुरोध के लिए एक नए पहचानकर्ता का उपयोग किया जाना चाहिए, जिससे किसी और के सत्र का उपयोग करने की संभावना कम हो जाएगी। लेकिन हम सामान्य मामले पर विचार करेंगे जब सत्र पहचानकर्ता पुनर्जनन समय मनमाने ढंग से निर्धारित किया जाता है।

(हम कोड के उस भाग को छोड़ देंगे जिस पर पहले ही चर्चा की जा चुकी है)।

फ़ंक्शन प्रारंभ सत्र ($isUserActivity=true) ( ​​// सत्र पहचानकर्ता जीवनकाल $idLifetime = 60; ... यदि ($idLifetime) ( // यदि सत्र पहचानकर्ता जीवनकाल सेट है, // सत्र के बाद से बीता हुआ समय जांचें बनाया गया या अंतिम पुनर्जनन // (अंतिम अनुरोध का समय जब सत्र चर प्रारंभ समय अद्यतन किया गया था) यदि (isset($_SESSION["starttime"])) ( यदि ($t-$_SESSION["starttime"] >= $ idLifetime) ( // वह समय जब सत्र पहचानकर्ता का जीवन समाप्त हो गया है // एक नया पहचानकर्ता session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) अन्यथा ( // यदि सत्र अभी समाप्त हुआ है तो हम यहां पहुंचेंगे बनाया गया // सत्र पहचानकर्ता को वर्तमान समय पर उत्पन्न करने के लिए समय निर्धारित करें $_SESSION["starttime"] = $t; ) ) return true; )

इसलिए, एक नया सत्र बनाते समय (जो तब होता है जब उपयोगकर्ता सफलतापूर्वक लॉग इन करता है), हम सत्र चर स्टार्टटाइम सेट करते हैं, जो हमारे लिए सत्र पहचानकर्ता की अंतिम पीढ़ी के समय को वर्तमान सर्वर समय के बराबर मान पर संग्रहीत करता है। इसके बाद, प्रत्येक अनुरोध में, हम जांचते हैं कि पहचानकर्ता की पिछली पीढ़ी के बाद से पर्याप्त समय (idLifetime) बीत चुका है या नहीं, और यदि हां, तो हम एक नया उत्पन्न करते हैं। इस प्रकार, यदि पहचानकर्ता के निर्धारित जीवनकाल के दौरान अधिकृत उपयोगकर्ता की कुकी प्राप्त करने वाले हमलावर के पास इसका उपयोग करने का समय नहीं है, तो नकली अनुरोध को सर्वर द्वारा अनधिकृत माना जाएगा, और हमलावर को लॉगिन पृष्ठ पर ले जाया जाएगा .

नोट: जब session_regenerate_id() फ़ंक्शन को कॉल किया जाता है, तो नई सत्र आईडी ब्राउज़र की कुकी में आ जाती है, जो session_start() फ़ंक्शन के समान नई कुकी भेजती है, इसलिए हमें कुकी को स्वयं अपडेट करने की आवश्यकता नहीं है।

यदि हम अपने सत्रों को यथासंभव सुरक्षित बनाना चाहते हैं, तो पहचानकर्ता के जीवनकाल को एक पर सेट करना या यहां तक ​​कि ब्रैकेट से session_regenerate_id() फ़ंक्शन को हटा देना और सभी चेक को हटा देना पर्याप्त है, जिससे प्रत्येक में पहचानकर्ता का पुनर्जनन हो जाएगा। अनुरोध। (मैंने प्रदर्शन पर इस दृष्टिकोण के प्रभाव का परीक्षण नहीं किया है, और मैं केवल यह कह सकता हूं कि session_regenerate_id(true) फ़ंक्शन अनिवार्य रूप से केवल 4 क्रियाएं करता है: एक नया पहचानकर्ता उत्पन्न करना, सत्र कुकी के साथ एक हेडर बनाना, पुराने को हटाना और बनाना एक नई सत्र फ़ाइल)।

गीतात्मक विषयांतर: यदि ट्रोजन इतना स्मार्ट हो जाता है कि वह हमलावर को कुकीज़ नहीं भेजता है, लेकिन कुकी प्राप्त होने पर तुरंत पूर्व-तैयार नकली अनुरोध भेजने का आयोजन करता है, तो ऊपर वर्णित विधि संभवतः सक्षम नहीं होगी इस तरह के हमले से बचाएं, क्योंकि ट्रोजन द्वारा कुकी प्राप्त करने और नकली अनुरोध भेजने के बीच व्यावहारिक रूप से कोई अंतर नहीं होगा, और इस बात की बहुत अधिक संभावना है कि इस समय सत्र पहचानकर्ता को पुनर्जीवित नहीं किया जाएगा।

कई उपयोगकर्ताओं की ओर से एक ब्राउज़र में एक साथ काम करने की संभावना अंतिम कार्य जिस पर मैं विचार करना चाहूंगा वह कई उपयोगकर्ताओं द्वारा एक ब्राउज़र में एक साथ काम करने की संभावना है। यह सुविधा परीक्षण चरण में विशेष रूप से उपयोगी है, जब आपको उपयोगकर्ताओं के एक साथ काम का अनुकरण करने की आवश्यकता होती है, और संपूर्ण उपलब्ध शस्त्रागार का उपयोग करने या गुप्त मोड में ब्राउज़र के कई उदाहरण खोलने के बजाय, इसे अपने पसंदीदा ब्राउज़र में करने की सलाह दी जाती है। .

हमारे पिछले उदाहरणों में, हमने स्पष्ट रूप से सत्र नाम निर्दिष्ट नहीं किया था, इसलिए डिफ़ॉल्ट PHP नाम (PHPSESSID) का उपयोग किया गया था। इसका मतलब यह है कि हमने अब तक जितने भी सत्र बनाए हैं, उनमें PHPSESSID नाम से ब्राउज़र को एक कुकी भेजी गई है। जाहिर है, यदि कुकी का नाम हमेशा एक ही है, तो एक ही ब्राउज़र में एक ही नाम से दो सत्र आयोजित करने का कोई तरीका नहीं है। लेकिन यदि हम प्रत्येक उपयोगकर्ता के लिए अपना स्वयं का सत्र नाम उपयोग करें, तो समस्या हल हो जाएगी। चलो ऐसा करते हैं.

फ़ंक्शन प्रारंभ सत्र($isUserActivity=true, $prefix=null) (... यदि (session_id()) सत्य लौटाता है; // यदि उपयोगकर्ता उपसर्ग पैरामीटर में पारित किया गया है, // एक अद्वितीय सत्र नाम सेट करें जिसमें यह शामिल है उपसर्ग, // अन्यथा सभी उपयोगकर्ताओं के लिए सामान्य नाम सेट करें (उदाहरण के लिए, MYPROJECT) session_name("MYPROJECT"।($prefix ? "_"।$prefix: "")); ini_set("session.cookie_lifetime", 0); अगर (! session_start()) झूठी वापसी; ...)

अब जो कुछ बचा है वह यह सुनिश्चित करना है कि कॉलिंग स्क्रिप्ट प्रत्येक उपयोगकर्ता के लिए स्टार्टसेशन() फ़ंक्शन के लिए एक अद्वितीय उपसर्ग पास करती है। यह किया जा सकता है, उदाहरण के लिए, प्रत्येक अनुरोध के GET/POST पैरामीटर में एक उपसर्ग पास करके या एक अतिरिक्त कुकी के माध्यम से।

निष्कर्ष अंत में, मैं ऊपर चर्चा किए गए सभी कार्यों सहित, PHP सत्रों के साथ काम करने के लिए हमारे कार्यों का पूरा अंतिम कोड प्रदान करूंगा।

फ़ंक्शन प्रारंभ सत्र ($isUserActivity=true, $prefix=null) ( $sessionLifetime = 300; $idLifetime = 60; यदि (session_id()) सही लौटाता है; session_name("MYPROJECT"।($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; ) ) अन्य ( $_SESSION["starttime"] = $t; ) ) रिटर्न true; ) फ़ंक्शन नष्ट सत्र() ( यदि (session_id()) ( session_unset(); setcookie(session_name(), session_id(), time() -60*60*24); session_destroy(); ) )

मुझे उम्मीद है कि यह लेख उन लोगों के लिए कुछ समय बचाएगा जिन्होंने सत्र तंत्र में कभी भी गहराई से प्रवेश नहीं किया है, और उन लोगों के लिए इस तंत्र में पर्याप्त अंतर्दृष्टि प्रदान करेगा जो अभी PHP से परिचित होना शुरू कर रहे हैं।

क्या आपको उपयोगकर्ता नाम और पासवर्ड की आवश्यकता है?

लेखों को ऑनलाइन सबमिट करने और सबमिट किए गए लेखों की स्थिति की जांच करने के लिए, आपको पंजीकरण करना होगा और अपने खाते में लॉग इन करना होगा।

प्रस्तुत करने हेतु लेख तैयार करने हेतु चेकलिस्ट

लेख प्रस्तुत करने की प्रक्रिया के भाग के रूप में, लेखकों को यह जांचना चाहिए कि उनका लेख निम्नलिखित सभी बिंदुओं को पूरा करता है; यदि वे इन आवश्यकताओं को पूरा नहीं करते हैं तो लेख लेखकों को वापस कर दिए जा सकते हैं।

आलेख आवश्यकताओं के अनुरूप तैयार किया गया है

कॉपीराइट के हस्तांतरण की शर्तें

लेखक काम का कॉपीराइट बरकरार रखते हैं और क्रिएटिव कॉमन्स एट्रिब्यूशन लाइसेंस की शर्तों के तहत लाइसेंस देते हुए, काम के साथ जर्नल को पहले प्रकाशन का अधिकार देते हैं, जो दूसरों को काम के लेखक और एक लिंक के अनिवार्य श्रेय के साथ इस काम को वितरित करने की अनुमति देता है। इस पत्रिका में मूल प्रकाशन के लिए.

गोपनीयता वाले कथन

इस पत्रिका की वेबसाइट में दर्ज किए गए नाम और ईमेल पते केवल इस पत्रिका द्वारा निर्दिष्ट उद्देश्यों के लिए उपयोग किए जाएंगे और किसी अन्य उद्देश्य के लिए उपयोग नहीं किए जाएंगे या किसी अन्य व्यक्ति या इकाई को प्रदान नहीं किए जाएंगे।

सिस्टम में पंजीकरण करने से पहले, उपयोगकर्ता व्यक्तिगत डेटा के प्रसंस्करण और भंडारण के लिए नीति से सहमत होता है।

लेखक भुगतान

रिक्त स्थान के साथ 1500 अक्षर: 300.00 (आरयूबी)

पांडुलिपि के 1 पृष्ठ का प्रकाशन (1500 अक्षर) - 300 रूबल। ग्राफिक सामग्री/टेबल का भुगतान अलग से किया जाता है - 50 रूबल / 1 टुकड़ा। लेखक की प्रतिलिपि, रूस के भीतर शिपिंग सहित, लेखक के अनुरोध पर भुगतान किया जाता है - 400 रूबल। विदेश में शिपिंग - 800 रूबल। प्रकाशन के लिए सामग्री की स्वीकृति का प्रमाण पत्र भेजने की लागत 150 रूबल है।

संबंधित जानकारी (लेखकों का पूरा नाम, काम का स्थान; शीर्षक; सार; कीवर्ड) का अंग्रेजी में अनुवाद, रिक्त स्थान सहित प्रत्येक वर्ण के लिए 0.5 रूबल।

ध्यान! लेखक (उम्मीदवार और विज्ञान के डॉक्टर) जिनके पास elibrary.ru के अनुसार 300 या अधिक उद्धरण हैं (स्व-उद्धरण का हिस्सा 30% से अधिक नहीं होना चाहिए) को निःशुल्क प्रकाशित किया जाता है। यदि आप निःशुल्क प्रकाशन के लिए पात्र हैं, तो सामग्री सबमिट करते समय, टिप्पणी क्षेत्र में, उद्धरणों की संख्या के साथ अपने पुस्तकालय प्रोफ़ाइल का लिंक इंगित करें। संग्रह के लिए शिपिंग लागत का भुगतान अलग से किया जाता है।

वेबसाइट सुरक्षा सत्र प्रबंधन पर आधारित है। जब कोई उपयोगकर्ता किसी सुरक्षित साइट से जुड़ता है, तो वे आमतौर पर उपयोगकर्ता नाम और पासवर्ड के रूप में क्रेडेंशियल प्रदान करते हैं। वेब सर्वर को पता नहीं है कि कौन सा उपयोगकर्ता पहले से लॉग इन है या वे एक पेज से दूसरे पेज पर कैसे नेविगेट करते हैं। सत्र तंत्र उपयोगकर्ताओं को हर बार कोई नई कार्रवाई करने या किसी नए पृष्ठ पर जाने के लिए पासवर्ड दर्ज करने से रोकता है।

अनिवार्य रूप से, सत्र प्रबंधन यह सुनिश्चित करता है कि वर्तमान में जुड़ा हुआ उपयोगकर्ता वही है जिसे प्रमाणित किया गया था। लेकिन दुर्भाग्य से, सत्र हैकर्स के लिए एक स्पष्ट लक्ष्य बन गए हैं क्योंकि वे प्रमाणीकरण की आवश्यकता के बिना वेब सर्वर तक पहुंच की अनुमति दे सकते हैं।

उपयोगकर्ता के प्रमाणित होने के बाद, वेब सर्वर उसे एक सत्र आईडी प्रदान करता है। यह आईडी ब्राउज़र में संग्रहीत होती है और जब भी प्रमाणीकरण की आवश्यकता होती है तो इसे प्रतिस्थापित किया जाता है। यह आपको बार-बार लॉगिन/पासवर्ड प्रविष्टि प्रक्रियाओं से बचने की अनुमति देता है। यह सब पृष्ठभूमि में होता है और उपयोगकर्ता को असुविधा नहीं होती है। कल्पना कीजिए कि हर बार जब आप कोई नया पृष्ठ देखते हैं तो आप अपना उपयोगकर्ता नाम और पासवर्ड दर्ज करते हैं!

इस लेख में मैं PHP में सत्र आईडी की सुरक्षा के लिए उन सभी तरीकों की रूपरेखा तैयार करने का प्रयास करूंगा जो मैं जानता हूं।

कुकीज़ का उपयोग करना डिफ़ॉल्ट रूप से, आईडी सहित सभी सत्र जानकारी एक कुकी को भेजी जाती है। लेकिन ऐसा हमेशा नहीं होता. कुछ उपयोगकर्ता अपने ब्राउज़र में कुकीज़ अक्षम कर देते हैं। इस स्थिति में, ब्राउज़र यूआरएल में सत्र आईडी पास करेगा।

जब जानकारी HTTP हेडर में छिपी होती है, तो कुकी के माध्यम से सत्र के विपरीत, यहां आईडी स्पष्ट पाठ में प्रसारित होती है। इससे बचाव का सबसे सरल तरीका एड्रेस बार के माध्यम से सत्र पहचानकर्ता के प्रसारण को प्रतिबंधित करना होगा। यह अपाचे सर्वर .htaccess कॉन्फ़िगरेशन फ़ाइल में निम्नलिखित लिखकर किया जा सकता है:

Php_flag session.use_only_cookies चालू

एन्क्रिप्शन का उपयोग करना यदि आपकी साइट को संवेदनशील जानकारी, जैसे क्रेडिट कार्ड नंबर (सोनी से हैलो) संसाधित करनी है, तो आपको SSL3.0 या TSL1.0 एन्क्रिप्शन का उपयोग करना चाहिए। ऐसा करने के लिए, कुकी सेट करते समय, आपको सुरक्षित पैरामीटर के लिए सही निर्दिष्ट करना होगा।

यदि आप सत्र पासवर्ड को $_SESSION वेरिएबल में संग्रहीत करते हैं (एसक्यूएल का उपयोग करना अभी भी बेहतर है), तो आपको इसे स्पष्ट टेक्स्ट में संग्रहीत नहीं करना चाहिए।

यदि ($_SESSION["password"] == $userpass) ( // कोड )

उपरोक्त कोड सुरक्षित नहीं है क्योंकि पासवर्ड एक सत्र चर में सादे पाठ के रूप में संग्रहीत किया जाता है। इसके बजाय, md5 एन्क्रिप्शन का उपयोग करें, कुछ इस तरह:

यदि ($_SESSION["md5password"] == md5($userpass)) ( // कोड )

ब्राउज़र जांच किसी अन्य ब्राउज़र (कंप्यूटर) से सत्र का उपयोग करने की संभावना को रोकने के लिए, आपको उपयोगकर्ता-एजेंट HTTP हेडर फ़ील्ड की जांच दर्ज करनी चाहिए:

सत्र_प्रारंभ(); यदि (isset($_SESSION["HTTP_USER_AGENT"])) ( यदि ($_SESSION["HTTP_USER_AGENT"] != md5($_SERVER["HTTP_USER_AGENT"])) ( // कोड ) ) अन्यथा ( $_SESSION["HTTP_USER_AGENT" ] = md5($_SERVER["HTTP_USER_AGENT"]); )

सत्र समाप्ति सत्र के जीवनकाल, साथ ही कुकीज़ की समाप्ति समय को सीमित करें। डिफ़ॉल्ट रूप से, सत्र की अवधि 1440 सेकंड है। आप इस मान को php.ini और .htaccess के माध्यम से बदल सकते हैं। .htaccess के लिए उदाहरण:

# सत्र जीवनकाल सेकंड में
php_value session.gc_maxlifetime 3600
# कुकी का जीवनकाल सेकंड में
php_value session.cookie_lifetime 3600

आईपी ​​पते से बाइंडिंग कुछ स्थितियों में (हमेशा नहीं), आपको आईपी पते से बाइंड करना चाहिए। मुख्यतः जब उपयोगकर्ताओं की संख्या सीमित हो और उनके पास स्थिर आईपी हों। जाँच या तो अनुमत आईपी पतों की सूची पर आधारित हो सकती है,

शामिल करें('ip_list.php'); //$ip_white_list = सरणी ("एडमिन1" => "111.222.333.444", "एडमिन2" => "555.666.777.888"); if(!empty(array_search($_SERVER["REMOTE_ADDR"],$ip_white_list))) ( हेडर("स्थान: admin.php"); ) else ( echo "ACCESS DENY!"; )

या प्रत्येक अनुरोध के लिए आईपी पते द्वारा (केवल स्थिर आईपी के लिए):

यदि(isset($_SESSION["ip"]) और $_SESSION["ip"] == $_SERVER["REMOTE_ADDR"]) ( हेडर("स्थान: admin.php"); ) अन्यथा ( session_unset(); $ _सत्र["आईपी"] = $_सर्वर["रिमोट_एडीडीआर"]; )

आपको पता होना चाहिए कि हैकिंग से पूरी तरह बचा नहीं जा सकता। आप केवल किसी ज्ञात माध्यम से ही इस हैक को यथासंभव कठिन बना सकते हैं। हालाँकि, आपको अपने कानूनी उपयोगकर्ताओं के बारे में भी नहीं भूलना चाहिए, ताकि ऐसी सुरक्षा से उनका जीवन जटिल न हो।

यह लेख 2009 में लिखा गया था और यह हमारी सबसे लोकप्रिय पोस्टों में से एक है। यदि आप PHP और MySQL के बारे में अधिक जानने के इच्छुक हैं, तो यह आपके लिए बहुत रुचिकर हो सकता है।

ध्यान दें: इस आलेख को PHP 4.2 या बाद के संस्करण पर काम करने के लिए नया अद्यतन किया गया है!

हाल ही में, मुझे लोगों के एक समूह के साथ एक छोटे प्रोजेक्ट पर काम करने का अवसर मिला। हमने पहले ही तय कर लिया था कि अकेले ईमेल सभी को सूचित रखने के लिए पर्याप्त नहीं होगा, इसलिए मुझे परियोजना के लिए एक छोटी वेब साइट बनाने का काम सौंपा गया था। इसमें एक साधारण संदेश बोर्ड, एक ऐसा स्थान होगा जहां हम टीम के बाकी सदस्यों के उपयोग के लिए दस्तावेज़ और अन्य फ़ाइलें अपलोड कर सकते हैं, और टीम के विभिन्न सदस्यों के लिए संपर्क जानकारी भी शामिल होगी।

इनमें से कई सुविधाओं के काम करने के लिए, मुझे पता था कि साइट के संबंधित हिस्सों तक पहुंचने से पहले मुझे उपयोगकर्ताओं को लॉग इन करना होगा। मुझे एक ऐसी प्रणाली की आवश्यकता थी जो उपयोगकर्ताओं को साइट तक पहुंचने के लिए उपयोगकर्ता आईडी के लिए पंजीकरण करने दे, फिर मेरी ओर से किसी भी हस्तक्षेप के बिना तुरंत उस आईडी का उपयोग करें।

इस लेख में, मैं अपने द्वारा विकसित सिस्टम का एक सिंहावलोकन प्रदान करूंगा, जो उपयोगकर्ता साइनअप प्रक्रिया के साथ पहली छमाही में शुरू होगा। दूसरे भाग में, मैं साइट पर ही ध्यान केंद्रित करूंगा कि कैसे उपयोगकर्ताओं को लॉग इन करने की आवश्यकता होती है और फिर उनकी विजिट के दौरान उस लॉग-इन स्थिति को बनाए रखा जाता है। मैं PHP में सत्र प्रबंधन सुविधाओं के उपयोग पर विशेष ध्यान दूंगा। अंत में, आपके पास अपनी खुद की एक समान प्रणाली लागू करने के लिए आवश्यक सभी जानकारी होनी चाहिए।

इस पूरे लेख में, मैं यह मानूंगा कि आपको PHP भाषा, PHP स्क्रिप्ट में जानकारी सबमिट करने के लिए फ़ॉर्म के उपयोग और MySQL डेटाबेस के साथ इंटरैक्ट करने के लिए PHP का उपयोग कैसे किया जा सकता है, से बुनियादी परिचितता है। यदि इनमें से कोई भी आपके लिए विदेशी अवधारणा है, तो आपको मेरा पिछला लेख पढ़कर शुरुआत करनी चाहिए।

भाग एक: साइनअप प्रक्रिया साइनअप फॉर्म

किसी साइट का निर्माण शुरू करने के लिए एक प्राकृतिक स्थान जिसके उपयोग के लिए उपयोगकर्ताओं को पंजीकरण करना होगा, वह पंजीकरण प्रक्रिया ही है। जैसा कि कोई उम्मीद करेगा, एक सरल वेब-आधारित फॉर्म काम करेगा। यह इस प्रकार दिखेगा:

और इस फॉर्म के लिए कोड यहां दिया गया है:




नया उपयोगकर्ता पंजीकरण



नया उपयोगकर्ता पंजीकरण फॉर्म

* एक आवश्यक फ़ील्ड इंगित करता है


अब उद्देश्य स्पष्ट होने के साथ, मैं आपको accesscontrol.php के कोड के बारे में बताऊंगा। अपनी दो उपयोगी फ़ाइलों को शामिल करके शुरुआत करें: