قائمة الطعام
مجانا
التسجيل
الصفحة الرئيسية  /  الملاحون/ عمر ملف تعريف الارتباط php. ملفات تعريف الارتباط PHP - إنشاء وقراءة وحذف

عمر ملف تعريف الارتباط php. ملفات تعريف الارتباط PHP - إنشاء وقراءة وحذف

مرحبا عزيزي المجتمع.

بادئ ذي بدء ، أود أن أشكرك على مورد مفيد للغاية. لقد وجدت هنا أكثر من مرة الكثير من الأفكار الشيقة والنصائح العملية.

الغرض من هذه المقالة هو تسليط الضوء على مخاطر استخدام الجلسات في PHP. بالطبع ، هناك توثيق PHP والعديد من الأمثلة ، وليس المقصود من هذه المقالة أن تكون كذلك دليل كامل... إنه مصمم للكشف عن بعض الفروق الدقيقة في العمل مع الجلسات ولحماية المطورين من إضاعة الوقت دون داع.

حالة الاستخدام الأكثر شيوعًا للجلسات هي ، بالطبع ، إذن المستخدم. لنبدأ بالتنفيذ الأساسي حتى نتمكن من تطويره باستمرار مع ظهور تحديات جديدة.

(من أجل توفير المساحة والوقت ، سنقتصر في الأمثلة على وظائف العمل مع الجلسات فقط ، بدلاً من إنشاء تطبيق اختبار كامل هنا مع تسلسل هرمي جميل للفئة ومعالجة شاملة للأخطاء وأشياء صحيحة أخرى).

Function startSession () (// إذا كانت الجلسة قد بدأت بالفعل ، أوقف التنفيذ وأعد TRUE // (يجب تعطيل معلمة session.auto_start في ملف إعدادات php.ini - القيمة الافتراضية) إذا عادت (session_id ()) true؛ else return session_start ()؛ // ملاحظة: قبل الإصدار 5.3.0 ، أعادت الدالة session_start () القيمة TRUE حتى في حالة حدوث خطأ. // إذا كنت تستخدم إصدارًا أقل من 5.3.0 ، فقم بإجراء تحقق إضافي من session_id ( ) // بعد استدعاء session_start ()) وظيفة إتلاف الجلسة () (إذا (session_id ()) (// إذا كانت هناك جلسة نشطة ، فاحذف ملفات تعريف الارتباط للجلسة و setcookie (session_name () و session_id () والوقت () - 60 * 60 * 24) ؛ // وتدمير الجلسة session_unset () ؛ session_destroy () ؛))

ملحوظة:من المفترض أن القارئ لديه معرفة أساسية بجلسات PHP ، لذلك لن نغطي كيفية عمل الدالتين session_start () و session_destroy (). لا تتعلق مهام تخطيط نموذج تسجيل الدخول ومصادقة المستخدم بموضوع المقالة ، لذلك سنحذفها أيضًا. اسمح لي فقط أن أذكرك أنه لتحديد هوية المستخدم في كل طلب لاحق ، في لحظة تسجيل الدخول الناجح ، نحتاج إلى حفظ معرف المستخدم في متغير جلسة (مع اسم userid ، على سبيل المثال) ، والذي سيكون متاحًا في كل ما بعد الطلبات خلال عمر الجلسة. من الضروري أيضًا تنفيذ معالجة نتيجة وظيفة startSession () الخاصة بنا. إذا أرجعت الوظيفة FALSE ، اعرض نموذج تسجيل الدخول في المستعرض. إذا كانت الوظيفة ترجع TRUE ، وكان متغير الجلسة الذي يحتوي على معرف المستخدم المصرح له (في حالتنا ، معرف المستخدم) موجودًا ، فقم بعرض صفحة المستخدم المصرح له (لمزيد من التفاصيل حول معالجة الأخطاء ، راجع الإضافة من 2013-06- 07 في قسم متغيرات الجلسة).

حتى الآن ، كل شيء واضح. تبدأ الأسئلة عندما يكون مطلوبًا تنفيذ التحكم في عدم نشاط المستخدم (مهلة الجلسة) ، وتمكين العديد من المستخدمين من العمل في وقت واحد في متصفح واحد ، وكذلك حماية الجلسات من الاستخدام غير المصرح به. سيتم مناقشة هذا أدناه.

التحكم في عدم نشاط المستخدم باستخدام أدوات PHP المدمجة

السؤال الأول الذي يطرح نفسه غالبًا بين مطوري جميع أنواع وحدات التحكم للمستخدمين هو النهاية التلقائية للجلسة في حالة عدم النشاط من جانب المستخدم. لا يمكن أن يكون أسهل من استخدام إمكانيات PHP المدمجة. (هذا الخيار ليس مرنًا وموثوقًا به للغاية ، لكن دعنا نفكر فيه للتأكد من اكتماله).

الوظيفة startSession () (// مهلة عدم نشاط المستخدم (بالثواني) $ 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 () ، والوقت () + $ sessionLifetime) ؛ والعودة صحيحة ؛) وإلا إرجاع خطأ ؛)

تفسيرات قليلة. كما تعلم ، تحدد PHP الجلسة التي يجب أن تبدأ باسم ملف تعريف الارتباط الذي تم تمريره بواسطة المتصفح في رأس الطلب. يتلقى المتصفح بدوره ملف تعريف الارتباط هذا من الخادم ، حيث تضعه الوظيفة session_start (). إذا انتهت صلاحية ملف تعريف الارتباط في المتصفح ، فلن يتم إرساله في الطلب ، مما يعني أن PHP لن تكون قادرة على تحديد الجلسة التي ستبدأ ، وستعتبر هذا بمثابة إنشاء جلسة جديدة. معامل إعدادات PHP session.gc_maxlifetime ، التي يتم تعيينها على مهلة عدم نشاط المستخدم لدينا ، تحدد عمر جلسة PHP ويتم مراقبتها بواسطة الخادم. يعمل التحكم في مدة الجلسة على النحو التالي (نعتبر هنا مثالاً لتخزين الجلسة في الملفات المؤقتة باعتباره الإصدار الأكثر شيوعًا والافتراضي في PHP).

في وقت إنشاء جلسة جديدة ، يتم إنشاء ملف يسمى sess_ في الدليل الذي تم تعيينه كدليل لتخزين الجلسات في جلسة معلمة إعدادات PHP session.save_path. ، أين - معرف الجلسة. علاوة على ذلك ، في كل طلب ، في لحظة بدء جلسة حالية ، تقوم PHP بتحديث وقت تعديل هذا الملف. وبالتالي ، في كل طلب لاحق ، يمكن لـ PHP ، من خلال الاختلاف بين الوقت الحالي ووقت آخر تعديل لملف الجلسة ، تحديد ما إذا كانت الجلسة نشطة ، أو انتهت صلاحيتها بالفعل. (تمت مناقشة آلية حذف ملفات الجلسة القديمة بمزيد من التفصيل في القسم التالي).

ملحوظة:وتجدر الإشارة هنا إلى أن المعامل session.gc_maxlifetime يؤثر على جميع الجلسات داخل خادم واحد (بتعبير أدق ، في نطاق رئيسي واحد عملية PHP). من الناحية العملية ، هذا يعني أنه في حالة تشغيل عدة مواقع على الخادم ، وكان لكل منها مهلة عدم نشاط المستخدمين الخاصة به ، فإن تعيين هذه المعلمة على أحد المواقع سيؤدي إلى تثبيتها لمواقع أخرى أيضًا. الشيء نفسه ينطبق على الاستضافة المشتركة. لتجنب هذا الموقف ، يتم استخدام أدلة جلسة منفصلة لكل موقع داخل خادم واحد. يتم ضبط المسار إلى دليل الجلسة باستخدام المعامل session.save_path في ملف إعدادات php.ini ، أو باستدعاء الوظيفة ini_set (). بعد ذلك ، سيتم تخزين جلسات كل موقع في أدلة منفصلة ، وستكون المعلمة session.gc_maxlifetime ، المعينة على أحد المواقع ، صالحة فقط لجلستها. لن نفكر في هذه الحالة بالتفصيل ، خاصة وأن لدينا خيارًا أكثر مرونة للتحكم في عدم نشاط المستخدم.

التحكم في عدم نشاط المستخدم باستخدام متغيرات الجلسة

يبدو أن الخيار السابق ، بكل بساطته (مجرد سطرين إضافيين من التعليمات البرمجية) ، يوفر كل ما نحتاجه. ولكن ماذا لو لم يكن كل طلب يمكن اعتباره نتيجة لنشاط المستخدم؟ على سبيل المثال ، تحتوي الصفحة على مؤقت يقوم بشكل دوري بتقديم طلب AJAX لتلقي التحديثات من الخادم. لا يمكن اعتبار هذا الطلب نشاطًا للمستخدم ، مما يعني أن التمديد التلقائي لعمر الجلسة غير صحيح في هذه الحالة. لكننا نعلم أن PHP تُحدِّث وقت تعديل ملف الجلسة تلقائيًا مع كل استدعاء لوظيفة session_start () ، مما يعني أن أي طلب سيؤدي إلى تمديد عمر الجلسة ، ولن تحدث مهلة عدم نشاط المستخدم أبدًا. بالإضافة إلى ذلك ، قد تبدو الملاحظة الأخيرة من القسم السابق حول تعقيدات المعلمة session.gc_maxlifetime مربكة للغاية ومعقدة للغاية في التنفيذ.

لحل هذه المشكلة ، سنتخلى عن استخدام المدمج آليات PHPوسنقدم العديد من متغيرات الجلسة الجديدة التي ستسمح لنا بالتحكم في وقت عدم نشاط المستخدمين بمفردنا.

وظيفة startSession ($ isUserActivity = true) ($ sessionLifetime = 300 ؛ إذا كانت (session_id ()) تعود بالقيمة true ؛ // عيِّن عمر ملف تعريف الارتباط حتى يتم إغلاق المتصفح (سنتحكم في كل شيء على جانب الخادم) ini_set ("session.cookie_lifetime) "، 0)؛ إذا كانت (! session_start ()) ترجع خطأ ؛ $ t = time () ؛ إذا ($ sessionLifetime) (// إذا تم تعيين مهلة عدم نشاط المستخدم ، // تحقق من الوقت المنقضي منذ آخر نشاط للمستخدم / / (وقت الطلب الأخير عندما تم تحديث متغير جلسة النشاط الأخير) إذا كان (isset ($ _ SESSION ["lastactivity"]) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (// إذا كان انقضى الوقت منذ آخر نشاط للمستخدم / / مهلة عدم نشاط أكثر ، ثم انتهت صلاحية الجلسة ، وتحتاج إلى إنهاء الجلسة إتلاف الجلسة () ؛ إرجاع خطأ ؛) وإلا (// إذا لم تحدث المهلة بعد ، // وإذا جاء الطلب نتيجة نشاط المستخدم ، // تحديث متغير النشاط الأخير بقيمة vr الحالي emeny، // وبذلك يتم تمديد وقت الجلسة بجلسة أخرى وثواني مدى الحياة إذا ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t؛ )) العودة صحيحة ؛ )

دعونا نلخص. في كل طلب ، نتحقق مما إذا كان قد تم الوصول إلى المهلة من لحظة آخر نشاط للمستخدم إلى اللحظة الحالية ، وإذا تم الوصول إليها ، فإننا ندمر الجلسة ونقطع تنفيذ الوظيفة ، ونعيد FALSE. إذا لم يتم الوصول إلى المهلة ، وتم تمرير المعلمة $ isUserActivity بقيمة TRUE إلى الوظيفة ، فإننا نقوم بتحديث وقت آخر نشاط للمستخدم. كل ما يتعين علينا القيام به هو تحديد ما إذا كان الطلب ناتجًا عن نشاط المستخدم ، وإذا لم يكن الأمر كذلك ، فقم باستدعاء وظيفة startSession بقيمة المعلمة isUserActivity $ التي تساوي FALSE.

التحديث اعتبارًا من 2013-06-07
معالجة نتيجة وظيفة sessionStart ()

لاحظنا في التعليقات أن إرجاع FALSE لا يعطي فهمًا كاملاً لسبب الخطأ ، وهذا صحيح تمامًا. لم أنشر هنا معالجة الأخطاء التفصيلية (حجم المقالة ليس صغيراً على أي حال) ، لأن هذا لا يتعلق مباشرة بموضوع المقالة. لكن في ضوء التعليقات ، سأوضح.

كما ترى ، يمكن لوظيفة sessionStart إرجاع 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 ( ) استدعاء واستمرار تنفيذ البرنامج النصي ، سواء كان تصويتًا طويلاً أو طلبًا منتظمًا.

حماية الجلسات من الاستخدام غير المصرح به

دعونا نتخيل الموقف. يقوم أحد المستخدمين لديك بتوصيل حصان طروادة الذي يسرق ملف تعريف ارتباط المتصفح (الذي يتم تخزين جلستنا فيه) ويرسله إلى البريد الإلكتروني المحدد. يتلقى المهاجم ملف تعريف ارتباط ويستخدمه لتزوير طلب نيابة عن مستخدمنا المصرح له. يقبل الخادم هذا الطلب ويعالجه بنجاح كما لو كان من مستخدم مرخص له. إذا لم يتم تنفيذ تحقق إضافي من عنوان IP ، فسيؤدي هذا الهجوم إلى اختراق حساب المستخدم بنجاح مع كل العواقب المترتبة على ذلك.

لماذا هذا ممكن؟ من الواضح ، لأن الاسم ومعرف الجلسة يكونان دائمًا متطابقين طوال مدة الجلسة ، وإذا تلقيت هذه البيانات ، يمكنك إرسال الطلبات بحرية نيابة عن مستخدم آخر (بطبيعة الحال ، خلال عمر هذه الجلسة). ربما لا يكون هذا هو النوع الأكثر شيوعًا من الهجمات ، ولكن من الناحية النظرية يبدو كل شيء ممكنًا تمامًا ، لا سيما بالنظر إلى أن حصان طروادة لا يحتاج حتى إلى حقوق المسؤول لسرقة ملفات تعريف ارتباط متصفح المستخدم.

كيف يمكنك الدفاع ضد هجمات من هذا النوع؟ مرة أخرى ، من الواضح عن طريق تحديد عمر معرف الجلسة وتغيير المعرف بشكل دوري خلال جلسة واحدة. يمكننا أيضًا تغيير اسم الجلسة ، وحذف الاسم القديم تمامًا وإنشاء جلسة جديدة ، ونسخ جميع متغيرات الجلسة من المتغيرات القديمة إليها. لكن هذا لا يؤثر على جوهر النهج ، لذلك ، من أجل البساطة ، سنقتصر فقط على معرف الجلسة.

من الواضح أنه كلما كان عمر معرف الجلسة أقصر ، قل الوقت الذي سيحتاج فيه المهاجم إلى الحصول على ملفات تعريف الارتباط واستخدامها لتزوير طلب المستخدم. من الناحية المثالية ، يجب استخدام معرّف جديد لكل طلب ، مما سيقلل من إمكانية استخدام جلسة شخص آخر. لكننا سننظر في الحالة العامة حيث يتم تعيين وقت إعادة إنشاء معرف الجلسة بشكل تعسفي.

(دعنا نحذف جزء الكود الذي تمت مناقشته بالفعل).

وظيفة startSession ($ isUserActivity = true) (// عمر معرف الجلسة $ idLifetime = 60 ؛ ... إذا ($ idLifetime) (// إذا تم تعيين عمر معرّف الجلسة ، // تحقق من الوقت المنقضي منذ إنشاء الجلسة أو آخر تجديد // (وقت آخر طلب عندما تم تحديث وقت بدء متغير الجلسة) if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (// انتهت صلاحية معرف جلسة العمل // إنشاء معرف جديد session_regenerate_id (صحيح) ؛ $ _SESSION ["starttime"] = $ t ؛)) else (// نصل إلى هنا إذا تم إنشاء الجلسة للتو // تعيين وقت إنشاء معرف الجلسة في الوقت الحالي $ _SESSION ["starttime"] = $ t؛)) يعود صحيحًا ؛)

لذلك ، عند إنشاء جلسة جديدة (والتي تحدث عندما يقوم المستخدم بتسجيل الدخول بنجاح) ، نقوم بتعيين وقت بدء متغير الجلسة ، والذي يخزن لنا وقت الجيل الأخير من معرف الجلسة ، إلى قيمة مساوية لوقت الخادم الحالي. علاوة على ذلك ، في كل طلب ، نتحقق مما إذا كان الوقت الكافي (idLifetime) قد مر منذ الجيل الأخير من المعرّف ، وإذا مر ، فإننا ننشئ واحدًا جديدًا. وبالتالي ، إذا لم يتمكن المهاجم الذي تلقى ملف تعريف الارتباط الخاص بالمستخدم المعتمد خلال العمر المحدد للمعرف من استخدامه ، فسيعتبر الخادم الطلب المزيف غير مصرح به ، وسيتم نقل المهاجم إلى صفحة تسجيل الدخول.

ملحوظة:يدخل معرف الجلسة الجديد إلى ملف تعريف ارتباط المتصفح عندما يتم استدعاء وظيفة session_regenerate_id () ، والتي ترسل ملف تعريف ارتباط جديدًا ، مشابهًا لوظيفة session_start () ، لذلك لا نحتاج إلى تحديث ملفات تعريف الارتباط بأنفسنا.

إذا أردنا تأمين جلساتنا قدر الإمكان ، فهذا يكفي لتعيين عمر المعرف إلى واحد ، أو حتى وضع وظيفة session_regenerate_id () خارج الأقواس وإزالة جميع عمليات التحقق ، مما سيؤدي إلى تجديد المعرف في كل طلب. (لم أختبر تأثير هذا الأسلوب على الأداء ، ولا يمكنني إلا أن أقول إن وظيفة session_regenerate_id (true) تؤدي بشكل أساسي 4 إجراءات فقط: إنشاء معرف جديد ، وإنشاء رأس من ملف تعريف ارتباط الجلسة ، وحذف القديم ، و إنشاء ملف جلسة جديد).

استطراد غنائي:إذا تبين أن حصان طروادة ذكي للغاية لدرجة أنه لن يرسل ملفات تعريف الارتباط إلى المهاجم ، ولكنه ينظم بنفسه إرسال طلب مزيف مُعد مسبقًا فور استلام ملف تعريف الارتباط ، فمن المحتمل ألا تتمكن الطريقة الموضحة أعلاه من الحماية ضد مثل هذا الهجوم ، لأنه بين الوقت الذي يتلقى فيه حصان طروادة ملف تعريف الارتباط وإرسال الملف المزيف ، لن يكون هناك فرق عمليًا في الطلب ، وهناك احتمال كبير ألا يتم إعادة إنشاء معرف الجلسة في هذه المرحلة.

القدرة على العمل في وقت واحد في متصفح واحد نيابة عن عدة مستخدمين

المهمة الأخيرة التي أود التفكير فيها هي إمكانية العمل المتزامن في متصفح واحد لعدة مستخدمين. هذه الميزة مفيدة بشكل خاص في مرحلة الاختبار ، عندما تحتاج إلى محاكاة العمل المتزامن للمستخدمين ، ويُنصح بالقيام بذلك في متصفحك المفضل ، وعدم استخدام الترسانة المتاحة بالكامل أو فتح مثيلات متعددة من المتصفح في "وضع التصفح المتخفي" " الوضع.

في الأمثلة السابقة ، لم نقم بتعيين اسم الجلسة بشكل صريح ، لذلك تم استخدام اسم PHP الافتراضي (PHPSESSID). هذا يعني أن جميع الجلسات التي أنشأناها حتى الآن قد أرسلت ملفات تعريف الارتباط إلى المتصفح تحت اسم PHPSESSID. من الواضح أنه إذا كان اسم ملف تعريف الارتباط هو نفسه دائمًا ، فلا توجد طريقة داخل متصفح واحد لتنظيم جلستين باستخدام نفس الاسم... ولكن إذا استخدمنا اسم جلسة مختلفًا لكل مستخدم ، فسيتم حل المشكلة. لذلك سنفعلها.

وظيفة startSession ($ isUserActivity = true ، $ prefix = null) (... إذا كانت (session_id ()) تُرجع صحيحًا ؛ // إذا تم تمرير بادئة المستخدم في المعلمات ، // عيِّن اسم جلسة فريدًا يتضمن هذا بادئة ، // ، بخلاف ذلك ، عيِّن اسمًا شائعًا لجميع المستخدمين (على سبيل المثال ، MYPROJECT) اسم الجلسة ("MYPROJECT". ($ prefix؟ "_". $ prefix: ""))؛ ini_set ("session.cookie_lifetime" ، 0) ؛ إذا كانت (! session_start ()) ترجع خطأ ؛ ...)

كل ما تبقى الآن هو التأكد من أن البرنامج النصي الاستدعاء يمرر بادئة فريدة لكل مستخدم إلى وظيفة startSession (). يمكن القيام بذلك ، على سبيل المثال ، بتمرير بادئة في معلمات GET / POST لكل طلب ، أو من خلال ملف تعريف ارتباط إضافي.

استنتاج

في الختام ، سأقدم الكود النهائي الكامل لوظائفنا للعمل مع جلسات PHP ، بما في ذلك جميع المهام التي تمت مناقشتها أعلاه.

الدالة startSession ($ isUserActivity = true، $ prefix = null) ($ sessionLifetime = 300؛ $ idLifetime = 60؛ if (session_id ()) ترجع صحيحًا؛ اسم_الجلسة ("MYPROJECT". ($ Prefix؟ "_". $ Prefix: "")) ؛ ini_set ("session.cookie_lifetime"، 0)؛ if (! session_start ()) تُرجع خطأ ؛ $ t = time () ؛ if ($ sessionLifetime) (if (isset ($ _ SESSION ["lastactivity" ]) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (destructionSession ()؛ عودة خطأ؛) else (if ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t؛)) إذا ( $ idLifetime) (if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (session_regenerate_id (true)؛ $ _SESSION ["starttime"] = $ t؛)) else ($ _SESSION ["starttime"] = $ t؛)) إرجاع صحيح ؛) وظيفة التدمير () (if (session_id ()) (session_unset () ؛ setcookie (session_name () ، session_id () ، الوقت () -60 * 60 * 24) ؛ session_destroy () ؛))

نأمل أن توفر هذه المقالة بعض الوقت لأولئك الذين لم يدخلوا في آلية الجلسة مطلقًا ، وستعطي فهمًا كافيًا لهذه الآلية لأولئك الذين بدأوا للتو في التعرف على PHP.

Nuuu دعونا اكتشاف ذلك.

أولاً ، اقرأ عن HTTP على نفس الويكي. لا تحتاج إلى معرفة دقيقة ، ولكن يجب أن يكون لديك الحد الأدنى من الفهم لهيكل الطلبات / الردود ، وأن تفهم أن الطلب والاستجابة لهما رؤوس ونص (قد لا يكون هناك جسم ، اعتمادًا على نوع الطلب / استجابة).

هذا كل شيء. بسكويت. ملفات تعريف الارتباط تعيش على جانب المتصفح. يتم إرسالها عن طريق رأس HTTP لكل طلب إلى الخادم (حتى إذا كنت قد بحثت عن صور). هناك فقط ملفات تعريف الارتباط ، وهناك ملفات تعريف ارتباط http فقط. يمكن تمييز ملفات تعريف الارتباط حسب المضيف والمسار. كل هذا يمنحنا المرونة ويساعد في الأمان. في PHP ، تزودنا محتويات $ _COOKIE بـ SAPI. عندما تتلقى PHP طلبًا للمعالجة ، فإن SAPI المستخدم (php-fpm ، cgi ، mod_php لها تطبيقات SAPI الخاصة بها) في هذه اللحظةيأخذ رؤوس الطلب ونصه ، ويوزعهم ويملأ كل هذه المصفوفات العالمية الفائقة مثل $ _SERVER ، $ _GET ، بما في ذلك $ _COOKIE. كل ما أرسله العميل إلينا (الشيء الذي يجعل الطلبات هو العميل ، والشيء الذي يعالجها هو الخادم) ، ولا يرسل لنا المتصفح سوى ملفات تعريف الارتباط الممكنة بناءً على مكان إرسال الطلب. يتم تعيين ملفات تعريف الارتباط بواسطة رأس Set-Cookie في الاستجابة ، أي هنا تحتاج إلى قراءة المزيد ، من حيث المبدأ ، حول HTTP وليس عن PHP. تتيح لك PHP العمل مع هذه الأشياء. يمكنك تعيين ملفات تعريف الارتباط مباشرة من خلال العمل مع رؤوس الاستجابة باستخدام وظيفة الرأس. علاوة على ذلك ، إذا قمت بتعيين عمر ملفات تعريف الارتباط إلى 0 ، فسيتم إعادة تعيينها ، وليس الجلسة ، عند إغلاق المتصفح ، حيث سينسى كل ملفات تعريف الارتباط هذه.

هنا ... الجلسات ... ب جلسة PHPعادة ملف. فقط بعض الملفات ذات الاسم العشوائي. إذا تم تحديد Session.autostart ، على سبيل المثال ، في php.ini أو تم استدعاء session_start ، فسيتم إنشاء ملف لجلسة المستخدم (يمكنك نقله إلى redis أو memcache ، وسعة التخزين الخاصة بك ، وما إلى ذلك ، حسب احتياجاتك. يمكنك ذلك. أيضًا تشفير البيانات ، وهو ما يحدث افتراضيًا). هذا الملف له معرّف ، فقط بعض السلاسل العشوائية. وإذا لم يتم العثور على جلسة من الطلب السابق أثناء معالجة الطلب ، فسيتم إنشاء جلسة جديدة.

والآن نصل إلى الأكثر إثارة للاهتمام - كيف تربط PHP الجلسة من الطلب السابق بالطلب الحالي. وهنا كل شيء بسيط جدًا - ملفات تعريف الارتباط. عندما يتم تعيين جلسة إلى مستخدم ، يتم تعيين ملف تعريف ارتباط http فقط تلقائيًا (بحيث لا يتمكن الأشخاص السيئون من إخراج جلستنا من js) ملف تعريف ارتباط يتم كتابة معرف الجلسة فيه. في مصحح أخطاء المتصفح ، يمكنك معرفة ما إذا كان لديك ملف تعريف ارتباط PHPSESSID (يمكن تغيير الاسم في الإعدادات ، وبشكل عام ، يمكن ربط الجلسات ليس فقط من خلال ملفات تعريف الارتباط ، ولكن هذه أقلام أمان بالفعل) عند تجربة الجلسات.

عندما تتم معالجة طلب بواسطة SAPI ، في وجود session.autostart ، قبل البدء في إنشاء جلسة جديدة ، فإنه لا يزال يبحث لمعرفة ما إذا كان لدينا ملف تعريف ارتباط بمعرف جلسة ، والتحقق مما إذا كان يحتوي على واحد ، وإذا كان كذلك ، يهدأ ولا يخلق واحدة جديدة. نظرًا لأن الجلسة مرتبطة بملفات تعريف الارتباط ، يمكنك تعيين عمر ملف تعريف الارتباط هذا (في php.ini) وبالتالي ضبط عمر الجلسة.

هنا ... متى تستخدم ملفات تعريف الارتباط ومتى يتم الجلسات؟ يُنصح بفهم أنه كلما زادت البيانات في ملفات تعريف الارتباط (ولديها حد لعدد الكلمات) ، زاد عدد البيانات التي ننقلها لكل طلب. هذا ليس رائعًا عندما ، من أجل تلقي 1 كيلوبايت من البيانات ، يتعين علينا نقل بضعة كيلوبايت من ملفات تعريف الارتباط في الرؤوس. يركز الأشخاص على التحسين حتى يقومون بتخزين الصور في نطاقات منفصلة خالية من ملفات تعريف الارتباط لتقليل مقدار حركة المرور والحزم (عادةً ما تكون بسيطة طلب HTTPيناسب حجم حزمة TCP واحدة). إذا كنت بحاجة إلى العمل مع هذه البيانات من JS على أي صفحة ، على سبيل المثال ، اللغة التي حددها المستخدم من أجل تطبيق الترجمات أيضًا في JS ، فيجب عليك استخدام ملفات تعريف الارتباط. لكل شيء آخر ، من الأفضل استخدام الجلسات بالطبع. على أي حال ، في المراحل الأولى ، عندما يكون هناك شيء معقد للغاية ، لن تضطر إلى القيام به.

HTTP هو بروتوكول طلب عديم الحالة. هذا يعني أن المستخدم يرسل طلبًا ، ويستجيب الخادم لهذا الطلب دون تذكر الطلب لاحقًا. من أجل تتبع معلومات مهمة(على سبيل المثال ، تفضيلات المستخدم ، وإجراءات المستخدم ، وما إلى ذلك) على موقع الويب عندما تعليمات PHPيتم إنشاء ملفات تعريف الارتباط ، أو ملفات تعريف الارتباط. في هذه المقالة ، سأتحدث عن كيفية العمل مع ملفات تعريف الارتباط ، وكيف يجب إنشاؤها ، وما هي المعلمات التي تحتويها ، وكيف يمكنك حذفها.

ما هو ملف تعريف الارتباط؟

تعد ملفات تعريف الارتباط مفيدة جدًا لتخزين المعلومات مباشرة في متصفح المستخدم نفسه. انه سهل ملف نصيالذي يخزن بحد أقصى 4 كيلوبايت من البيانات.

يتم إنشاء ملفات تعريف الارتباط باستخدام المتصفح بناءً على طلب الخادم (وفقًا لمنطق البرنامج). بعد إنشاء ملف تعريف الارتباط من جانب المستخدم ، يرسل متصفح المستخدم هذه المعلومات (من ملف تعريف الارتباط) مرة أخرى إلى الخادم باستخدام رأس HTTP.

غالبًا ما تخزن ملفات تعريف الارتباط معلومات تسجيل الدخول وكلمات المرور والمزيد. على سبيل المثال ، تذهب إلى الموقع ، أدخل اسم المستخدم وكلمة المرور. يقوم الموقع تلقائيًا بإنشاء ملف تعريف ارتباط لك بهذه البيانات. وفي المرة التالية التي تزور فيها الموقع ، يقوم فقط بالتحقق من وجود ملفات تعريف الارتباط ، وتحميل بيانات المستخدم المحفوظة فيها.

// مثال لصفحة فهرس لمثل هذا الموقع إذا ($ _ COOKIE ["تسجيل الدخول"]) (العنوان ("الموقع: /lk/index.php؟login=".$_COOKIE [" تسجيل الدخول "]) ؛ / / التحويلات مباشرة إلى حسابك الشخصي) // التالي يأتي ، على سبيل المثال ، نموذج تسجيل الدخول والتسجيل

لماذا ملفات تعريف الارتباط؟

HTTP هو بروتوكول عديم الحالة ، لذلك لا توجد طريقة لتتبع إجراءات المستخدم السابقة على الموقع. ملفات تعريف الارتباط هي أفضل طريقةلتخزين البيانات. أعرف كل شيء عن ملفات تعريف الارتباط للرغبات ، التي تكسرها ، وداخل قطعة من الورق مع ما قد يحدث لك في المستقبل. بالنسبة لي ، من هنا تنمو الأرجل حول الاسم.

ملفات تعريف الارتباط PHP

في الواقع ، نظرًا لأنني أوضحت بالفعل ما هو عليه ، فلنتعرف على كيفية تعيين ملفات تعريف الارتباط في PHP.

نستخدم طريقة SetCookie () لتعيين ملفات تعريف الارتباط في متصفح المستخدم.

بناء الجملة لإعداد ملفات تعريف الارتباط في PHP

Setcookie (الاسم ، val ، الوقت ، المسار ، المجال ، آمن) ؛

الاسم - يحدد اسم ملف تعريف الارتباط.

val - القيمة التي نريد تخزينها في ملف تعريف الارتباط. يخزن ملف تعريف الارتباط دائمًا قيمة سلسلة.

الوقت (اختياري) - اضبط وقت انتهاء صلاحية ملف تعريف الارتباط. إذا كان هذا الحقل فارغًا ، فسيتم حذف ملفات تعريف الارتباط عند إغلاق المتصفح.

domain (اختياري) - حدد النطاق الذي يتوفر فيه ملف تعريف الارتباط. إذا كنت ترغب في تعيين ملفات تعريف الارتباط لنطاقات فرعية متعددة ، فاستخدم اسم المجال الرئيسي مع نقطة كبادئة.

على سبيل المثال:

دع my.com يحتوي على نطاقات فرعية متعددة مثل tech.my.com ، only.my.com. وأريد أن يكون ملف تعريف الارتباط الذي تم تعيينه في my.com متاحًا لجميع نطاقاتي الفرعية ، ثم قمت بتعيين النطاق كـ my.com.

آمن (اختياري) - يحدد هذا ما إذا كان يجب نقل ملف تعريف الارتباط عبر اتصال HTTPS آمن. الافتراضي هو FALSE. إذا تم ضبط هذا على صحيح ، فهذا يعني أنه سيتم إنشاء ملف تعريف الارتباط فقط في حالة وجود اتصال آمن ، ومن المنطقي أنه لن يتم إنشاؤه أثناء HTTP.

Setcookie ("تسجيل الدخول"، "valera123") ؛

باستخدام البرنامج النصي أعلاه ، سننشئ ملف تعريف ارتباط باسم تسجيل الدخول وبالقيمة valera123.

ملاحظة: يمكن لملفات تعريف الارتباط تخزين قيم السلسلة فقط. لا يمكنهم تخزين مجموعة. من أجل تخزين مصفوفة في ملفات تعريف الارتباط ، تحتاج أولاً إلى تحويلها إلى سلسلة. بالتأكيد سأتحدث عن هذا لاحقًا.

ملاحظة: كما لاحظت ، لم أقم بتعيين عمر ملف تعريف الارتباط الخاص بنا. هذا هو السبب في أنها ستختفي بعد إغلاق متصفحنا ...

سيتم تعيين ملف تعريف الارتباط الخاص بنا باستخدام طريقة SetCookie (). بعد تنفيذ البرنامج النصي بالطريقة المحددة ، يمكنك بسهولة التحقق من ملف تعريف الارتباط في لوحة المطورين في الكروم ، أو في Firebug في Firefox.


لم نحدد وقت انتهاء صلاحية ملف تعريف الارتباط. لنمنحه 30 يومًا. في هذه الحالة ، يجب أن نذكر الوقت. بعد ذلك ، سيعيش لمدة 30 يومًا حتى يحذفه المستخدم يدويًا.

Setcookie ("تسجيل الدخول" ، "valera123" ، الوقت () + 3600 * 24 * 30) ؛

3600 - 1 ساعة
24 - يوم
30 يوما

كيفية تعيين ملفات تعريف الارتباط للنطاقات الفرعية

setcookie ("تسجيل الدخول" ، "valera123" ، الوقت () + 3600 * 24 * 30 ، "/" ، ". my.com") ؛

حسنًا ، في الواقع ، تم تقديم هذا المثال بالفعل.

كيفية الحصول على قيمة ملف تعريف الارتباط في PHP

$ _COOKIE - يُستخدم للحصول على قيمة ملف تعريف الارتباط. يوجد أدناه رمز كيف يمكنك بالضبط الحصول على قيمة ملف تعريف الارتباط الذي تم تعيينه مسبقًا.

$ val = $ _COOKIE ["تسجيل الدخول"] ؛ صدى $ val؛ // سيتم إخراج valera123

كيفية إزالة ملفات تعريف الارتباط في PHP

لإزالة ملفات تعريف الارتباط في PHP ، قم بتعيين وقت سالب (الوقت المنقضي).

Setcookie ("تسجيل الدخول"، "valera123" ، الوقت () - 3600 * 24) ؛

إذن ماذا يحدث إذا حددنا وقتًا سالبًا. في هذه الحالة ، تنتهي صلاحية ملف تعريف الارتباط تلقائيًا.

نقاط مهمة حول ملفات تعريف الارتباط

1. يمكن للطاهي تخزين 4 كيلوبايت كحد أقصى من البيانات.

2. يمكنها فقط تخزين الخيوط.

3. لا يمكن الوصول إلى ملفات تعريف الارتباط إلا عن طريق المتصفح الذي يقوم بتعيينها. تعيين ملفات تعريف الارتباط متصفح كرومقد لا تكون متوفرة في متصفح Mozilla، أو غيره.

4. حاول تجنب تخزين البيانات السرية والحساسة للغاية في ملفات تعريف الارتباط.

في الواقع ، هذا كل شيء. آمل حقًا أن تكون قد أحببت هذا الخط ، وشاركنا رأيك في التعليقات ، ولا تنس أيضًا إعادة النشر.

فترة تشغيل متغيرات PHP $ _SESSION ، ونتيجة لذلك ، يعتمد نشاط تطبيقات الويب على مدة الجلسة. على سبيل المثال ، إذا كان المستخدم مرخصًا له في النظام ، فإن الوقت الذي يمكن أن يكون خلاله خاملاً دون الحاجة إلى إعادة إدخال تسجيل الدخول وكلمة المرور يعتمد على هذه المعلمة.

موجود طرق مختلفةتحديد عمر الجلسة. دعنا نحاول معرفة ذلك بمثال نظام التشغيللينكس.

كيفية معرفة عمر الجلسة

قبل إعداده ، يجدر النظر فيه الوضع الحالي... هناك عدة طرق للقيام بذلك:

1. على الخادم باستخدام الأمر php

php -i | جلسة grep

نحصل على قائمة المعلمات المتعلقة بالجلسات. نحن مهتمون بـ:

  • session.cookie_lifetime => 0 => 0
  • session.gc_maxlifetime => 1440 => 1440

هذه القيم هي الافتراضية. cookie_lifetime => 0يشير إلى عمل ملفات تعريف الارتباط حتى يتم إغلاق المتصفح ، إذا قمت بتعيين هذه المعلمة على قيمة معينة ، فستتوقف الجلسة أثناء تنشيط الجلسة ، لذلك من الأفضل تركها عند الصفر.

2. استخدام دالة php ini_get

$ maxlifetime = ini_get ("session.gc_maxlifetime") ؛
$ cookielifetime = ini_get ("session.cookie_lifetime") ؛

صدى $ maxlifetime ؛
صدى $ cookielifetime؛

إعادة تشغيل systemctl apache2 || إعادة تشغيل systemctl httpd

* في إصدارات Linux بدون systemd ، استخدم الأمر إعادة تشغيل خدمة apache2أو إعادة تشغيل خدمة httpd.

إذا استخدمنا FastCGI (PHP-FPM):

التخصيص عبر ملف htaccess

يسمح هذا الملف لمسؤول الموقع بإدارة بعض إعدادات خادم الويب. لتحريره ، تحتاج إلى الوصول إلى ملفات الموقع. لن تعمل الطريقة إذا لم يكن معالج PHP هو Apache ، ولكن ، على سبيل المثال ، NGINX + PHP-FPM. على الرغم من وجود طريقة (حول هذا الموضوع أدناه).

أضف ما يلي إلى ملف .htaccess:

php_value session.gc_maxlifetime 86400
php_value session.cookie_lifetime 0

* كما ترى ، فإن المعلمات هي نفسها عند التكوين عبر php.ini.

كما هو مذكور أعلاه ، لن تعمل هذه الطريقة ما لم يتم استخدام Apache. ومع ذلك ، يمكن إجراء التكوين على الخادم (مرة أخرى ، يجب أن يكون لدينا الوصول المناسب).

افتح ملف تكوين خادم الويب ، على سبيل المثال ، في php-fpm:

vi /etc/php-fpm.d/www.conf

وتحرير / إضافة:

php_value = 86400
php_value = 0

بعد إعادة تشغيل الخدمة:

إعادة تشغيل systemctl php-fpm || إعادة تشغيل خدمة php-fpm

تعيين معلمة في كود التطبيق

يمكن أن تكون هذه الطريقة مفيدة عند الحاجة إلى وجود صفحات بوابة مختلفة وقت مختلفجلسة الحياة. للقيام بذلك ، يمكنك استخدام وظائف PHP في ini_set و session_set_cookie_params ، على سبيل المثال:

Ini_set ("session.gc_maxlifetime" ، 86400) ؛
ini_set ("session.cookie_lifetime"، 0) ؛
session_set_cookie_params (0) ،

Session_start () ،

يجب استدعاء الوظائف قبل افتتاح الجلسة (session_start).

إقامة جلسة في التطبيق

قد تتجاوز بعض التطبيقات الإعدادات. في هذه الحالة ، من الضروري تعيين مدة الجلسة في معلمات البرنامج. لكل تطبيق إعداداته الخاصة ، والتي تحتاج إلى اكتشافها بنفسك. دعنا نعطي ، على سبيل المثال ، إعداد جلسة في CMS Bitrix.

اذهب إلى مجموعة المستخدمين- اختر مجموعة - أمان... ابحث عن المعلمة "مدة الجلسة (بالدقائق)" واضبط الوقت ، على سبيل المثال 1440 (24 ساعة بالدقائق).

كيفية تجديد الجلسات تلقائيًا

إذا تم إصدار الجلسة لفترة معينة وتنتهي في وقت محدد، قد يؤدي هذا إلى مقاطعة جلسة المستخدم النشطة. سيكون أكثر ملاءمة إذا تم تمديد مدة الجلسة تلقائيًا إذا قام الزائر بتحديث الصفحة. لهذا ، هناك المعلمة cookie_lifetime ، والتي حددناها في جميع الأمثلة أعلاه على 0.

إذا قمنا بتعيين قيمة cookie_lifetime إلى 86400 ، فسيتم إنهاء الجلسة بعد 24 ساعة. هذا ليس دائما مناسبا

إذا كانت هناك حاجة للتحكم في الجلسة ومقاطعتها ، فيمكنك استخدام وظيفة php session_destroy ().

مسار تخزين ملف الجلسة

يتم تعيين موقع تخزين ملفات الجلسة بواسطة المعلمة جلسةأيضا ، هذا هو وقت الحياة. بشكل افتراضي ، يمكن استخدام المسار / var / lib / php / Session.

هذه معلمة مهمة- إذا لم يكن لدى خادم الويب أذونات الكتابة إلى هذا الدليل ، فسيؤدي ذلك إلى استحالة تخزين الجلسات ، مما سيؤدي إلى نتائج غير متوقعة للتطبيقات.

لا يحتفظ خادم الويب باتصال دائم بالعميل ، ويتم التعامل مع كل طلب على أنه طلب جديد ، دون أي اتصال بالطلبات السابقة.
أي أنه لا يمكنك تتبع الطلبات من نفس الزائر أو حفظ المتغيرات له بين المشاهدات. صفحات فردية... تم اختراع الجلسات لحل هاتين المشكلتين.
في الواقع ، الجلسات ، باختصار ، هي آلية تسمح لك بتحديد متصفح فريد وإنشاء ملف لهذا المتصفح على الخادم ، والذي يخزن متغيرات الجلسة.

لن أصف بالتفصيل الحاجة إلى مثل هذه الآلية. هذه حالات كتب مدرسية مثل عربة التسوق في متجر إلكتروني ، والترخيص ، بالإضافة إلى المشكلات البسيطة تمامًا ، مثل ، على سبيل المثال ، حماية الأجزاء التفاعلية من الموقع من البريد العشوائي.

من حيث المبدأ ، من السهل جدًا إنشاء تناظري خاص بك للجلسات ، وليس وظيفيًا مثل PHP المدمج ، ولكنه متشابه في جوهره. على ملفات تعريف الارتباط وقاعدة البيانات.
عند طلب برنامج نصي ، نتطلع لمعرفة ما إذا كان ملف تعريف الارتباط قد وصل باسم معين. إذا لم يكن هناك ملف تعريف ارتباط ، فقم بتعيينه واكتب سطرًا جديدًا ببيانات المستخدم إلى قاعدة البيانات. إذا كان هناك ملف تعريف ارتباط ، فنحن نقرأ من قاعدة البيانات. بطلب واحد آخر ، نحذف السجلات القديمة من قاعدة البيانات ، والآن لدينا آلية جلسة جاهزة. إنه ليس صعبًا على الإطلاق. ولكن هناك بعض الفروق الدقيقة التي تجعل من الأفضل استخدام آلية الجلسة المدمجة.

إذا تم تمكين الأول فقط ، فعندئذ في بداية الجلسة (عند كل مكالمة بدء الجلسة ()) تم تثبيت ملف تعريف ارتباط للعميل. يقوم المستعرض بإرجاع ملف تعريف الارتباط هذا بشكل صحيح مع كل طلب تالٍ ، ولغة PHP معرّف جلسة. تبدأ المشاكل إذا لم يُرجع المتصفح ملفات تعريف الارتباط. في هذه الحالة ، ستبدأ PHP دائمًا جلسة جديدة دون تلقي ملفات تعريف الارتباط بمعرف ، ولن تعمل الآلية.

إذا تم تمكين الثانية فقط ، فلن يتم تعيين ملف تعريف الارتباط. وما يحدث هو ، من أجل ذلك ، في الأساس ، في الواقع ، من المفيد استخدام آلية الجلسة المضمنة. بعد أن يقوم البرنامج النصي بعمله ، وتشكيل الصفحة بالكامل ، تنظر PHP في كل شيء وتقوم بإلحاق معرف جلسة بكل رابط وبكل نموذج. يبدو شيئًا كالتالي:
فهرستحول الى
فهرس
ويتم إضافة حقل مخفي إلى النماذج

والمتصفح ، عندما تنقر على أي رابط ، أو عندما تضغط على زر في النموذج ، سيرسل الطلب المتغير الذي نحتاجه - معرّف الجلسة!
لأسباب واضحة ، تتم إضافة المعرف فقط إلى الروابط النسبية.

من الناحية النظرية ، في جلساتنا محلية الصنع حول ملفات تعريف الارتباط وقاعدة البيانات ، يمكنك تعيين نقل المعرف يدويًا إلى جميع الروابط يدويًا - وبعد ذلك ستعمل جلساتنا الخاصة بشكل مستقل عن ملفات تعريف الارتباط. لكن ، كما ترى - يكون الأمر أكثر متعة عندما يقوم شخص آخر بهذا العمل؟ ؛-)

يتم تمكين كلا الخيارين افتراضيًا في الإصدارات الحديثة من PHP. كيف تتعامل PHP مع هذا؟ يتم عرض الطباخ دائمًا. ويتم إكمال الروابط تلقائيًا فقط إذا لم تعثر PHP على ملف تعريف ارتباط بمعرف الجلسة. عندما يزور المستخدم الموقع لأول مرة خلال هذه الجلسة ، يحصل على ملف تعريف ارتباط ، وتتم إضافة الروابط. في الطلب التالي ، إذا كانت ملفات تعريف الارتباط مدعومة ، فإن PHP ترى ملف تعريف الارتباط وتتوقف عن إكمال الروابط. إذا لم تعمل ملفات تعريف الارتباط ، فستستمر PHP في إضافة معرف إلى الروابط بشكل صحيح ، ولن تُفقد الجلسة.
سيرى المستخدمون الذين لديهم ملفات تعريف ارتباط تعمل الارتباط الطويل بالمعرف مرة واحدة فقط.

فوه. مع الانتهاء من نقل المعرف.
الآن يبقى ربط ملف بالبيانات على جانب الخادم به.
PHP ستفعل هذا لنا. يكفي أن أكتب فقط
جلسة_ستارت () ،
$ _SESSION ["test"] = "أهلاً بالعالم!" ؛

وستقوم PHP بكتابة متغير الاختبار إلى الملف المرتبط بهذه الجلسة.
هناك نقطة مهمة جدا هنا.
مجموعة مصفوفة _SESSION دولار- مميز.
في الواقع ، هي المتغيرات التي نريد إتاحتها في نصوص مختلفة.
لوضع متغير في جلسة ما ، ما عليك سوى تخصيصه لعنصر من المصفوفة $ _SESSION.
للحصول على قيمتها ، يكفي الرجوع إلى نفس العنصر. سيكون المثال أدناه.

جمع القمامة - إزالة عفا عليها الزمن ملفات PHPكما أفعل ذلك بنفسي. بالإضافة إلى تشفير البيانات ومجموعة من الأشياء الضرورية الأخرى. نتيجة لهذه الرعاية ، فإن العمل مع الجلسات سهل للغاية.
ها نحن في الواقع ونأتي إلى مثال عمل الجلسات.
المثال صغير جدًا:
جلسة_ستارت () ،

صدى صوت "لقد قمت بتحديث هذه الصفحة"... _SESSION $ ["العداد"] ++. " ذات مرة. " ؛
صدى صوت "
تحديث "؛
?>

نتحقق مما إذا كان لدينا متغير عداد في الجلسة ، وإذا لم يكن كذلك ، فقم بإنشائه بقيمة 0 ، ثم قم بإخراج قيمته وزيادتها بمقدار واحد. ستتم كتابة القيمة المتزايدة في الجلسة ، وفي المرة التالية التي يتم فيها استدعاء النص ، سيكون للمتغير القيمة 1 ، وهكذا.
كل شيء بسيط للغاية.

من أجل الوصول إلى متغيرات الجلسة على أي صفحات من الموقع ، تحتاج إلى كتابة سطر واحد فقط (!) في بداية كل ملف نحتاج فيه إلى جلسات:
جلسة_ستارت () ،
ثم أشر إلى عناصر المصفوفة $ _SESSION. على سبيل المثال ، قد يبدو فحص التفويض بالشكل التالي:
جلسة_ستارت () ،
إذا ($ _SESSION ["مصرح به"]<> 1 ) {
header ("الموقع: /auth.php") ؛
خروج؛
}

إزالة المتغيرات من الجلسة.
إذا كان لديك register_globals = إيقاف ، فاكتب فقط
unset ($ _ SESSION ["var"]) ؛
إذا لم يكن ثم قربأحتاج أن أكتب معها
session_unregister ("var") ؛

الأخطاء الأكثر شيوعًا التي تظهر في PHP عند محاولة العمل مع الجلسات هي:
اثنين منهم،
تحذير: لا يمكن إرسال ملف تعريف الارتباط للجلسة - تم إرسال الرؤوس بالفعل
تحذير: لا يمكن إرسال محدد ذاكرة التخزين المؤقت للجلسة - تم إرسال الرؤوس بالفعل

بسبب نفس السبب ، يتم وصف الحل في هذه الحقيقة
ثالث،
تحذير: فشل فتح (/ tmp \ sess_SID، O_RDWR): لا يوجد مثل هذا الملف أو الدليل (2) في full_script_path على رقم السطر(كانت تبدو في السابق مثل تحذير: فشل في كتابة بيانات الجلسة (الملفات). يُرجى التحقق من صحة الإعداد الحالي لـ session.save_path (/ tmp)),
إذا تمت ترجمته من اللغة الإنجليزية ، فإنه يشرح المشكلة بالتفصيل: المسار المحدد في php.ini إلى الدليل حيث تمت كتابة ملفات الجلسة غير متوفر. هذا الخطأ هو الأسهل لإصلاح. ما عليك سوى كتابة دليل موجود وقابل للكتابة ، على سبيل المثال ،
session.save_path = c: \ windows \ temp
ولا تنس إعادة تشغيل Apache بعد ذلك.

كما اتضح ، الذكاء البشري ليس له حدود ، وبالتالي علي أن أوضح:
رسالة الخطأ الثالثة (تعذر العثور على الدليل) ستؤدي إلى "UNAVAILABLE" إلى أول رسالتين ، لأن رسالة الخطأ يتم إخراجها إلى المتصفح ولا يمكنك استخدام الرؤوس بعده. لذلك ، لا تتسرع في البحث عن نتيجة مبكرة ، ولكن اكتب أولاً المسار الصحيح!

المشكلة التالية الأكثر شيوعًا عند التعامل مع الجلسات هي الإرث الثقيل لـ register_globals. لا تعطِ متغيرات البرنامج النصي نفس أسماء مؤشرات المصفوفة $ _SESSION!
مع register_globals = on ، ستحل القيم محل بعضها البعض وستشعر بالارتباك.
وإذا كان register_globals = off ، فسيظهر خطأ آخر: "من المحتمل أن يعتمد البرنامج النصي الخاص بك على تأثير جانبي للجلسة كان موجودًا حتى PHP 4.2.3." ... للتخلص منه ، يجب عليك دائمًا تهيئة المتغيرات قبل الاستخدام (أو على الأقل التحقق من وجودها) وعدم إعطاء أسماء المتغيرات العامة التي تتطابق مع مؤشرات المصفوفة $ _SESSION.

إذا لم يعمل ، ولكن لم يتم عرض أي رسائل أيضًا ، فقم بإضافة سطرين في بداية البرنامج النصي المسؤولان عن عرض جميع الأخطاء على الشاشة - من المحتمل تمامًا وجود أخطاء ، لكنك ببساطة لا ترى معهم.
ini_set ("display_errors"، 1) ؛
error_reporting (E_ALL) ،

أو راجع أخطاء في error_log. بشكل عام ، يكون موضوع عرض رسائل الخطأ خارج نطاق هذه المقالة ، لذا تأكد على الأقل من إمكانية رؤيتها. يمكنك قراءة المزيد من التفاصيل حول استكشاف الأخطاء وإصلاحها في هذا القسم.

إذا كنت متأكدًا من عدم وجود أخطاء ، ولكن المثال المعطى لا يعمل على أي حال ، فمن المحتمل أن PHP لا تتيح نقل المعرف عبر عنوان url ، وملفات تعريف الارتباط لسبب ما لا تعمل.
انظر ما لديك مع ملفات تعريف الارتباط.
بشكل عام ، إذا كانت جلساتك "لا تعمل" ، فحاول أولاً نقل معرف الجلسة يدويًا ، أي إنشاء رابط وتعيين معرف له:
جلسة_ستارت () ،
if (! isset ($ _ SESSION ["counter"])) $ _SESSION ["counter"] = 0؛
صدى صوت "لقد قمت بتحديث هذه الصفحة"... _SESSION $ ["العداد"] ++. " ذات مرة.

تحديث "؛
?>

عند القيام بذلك ، تأكد من عدم تمكين التوجيه session.use_only_cookies ، مما يمنع PHP من قبول معرف الجلسة إذا تم تمريره عبر عنوان URL.

إذا لم يعمل هذا المثال ، فالمشكلة إما عادية الأخطاء المطبعية(نصف "مشاكل" الجلسات تأتي من اسم متغير به أخطاء إملائية) ، أو أيضًا نسخة قديمة PHP: تم تقديم دعم الجلسة في الإصدار 4.0 ، والمصفوفة _SESSION دولار- في الإصدار 4.1 (تم استخدامه سابقًا HTTP_SESSION_VARS دولار).
إذا نجحت ، فالمشكلة تكمن في ملفات تعريف الارتباط. تتبع نوع ملف تعريف الارتباط الذي يضعه الخادم في المتصفح ، سواء أكان المتصفح يعيده أم لا. يعد البحث مفيدًا جدًا أثناء النظر إلى تبادلات رأس HTTP بين المتصفح والخادم.
إن شرح كيفية عمل ملفات تعريف الارتباط هو خارج نطاق هذا النص الكبير بالفعل ، ولكن على الأقل تأكد من أن الخادم يرسل ملف تعريف الارتباط مع المعرف ، ويعود المتصفح. وبينما تتطابق المعرفات مع بعضها البعض =)
يجب أن يبدو إعداد ملف تعريف الارتباط
تعيين ملف تعريف الارتباط: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6 ؛
أو كيف
تعيين ملف تعريف الارتباط: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6 ؛ المسار = /
(إذا كنت تطلب برنامج نصي ليس من الدليل الجذر)
يجب أن تبدو استجابة الخادم بالشكل
ملف تعريف الارتباط: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6
أو
ملف تعريف الارتباط: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6 ؛ ب = ب
إذا قام المستعرض بإرجاع ملفات تعريف الارتباط الأخرى إلى جانب معرف الجلسة.

إذا لم يقم المتصفح بإرجاع ملفات تعريف الارتباط ، فتحقق مما إذا كانت ملفات تعريف الارتباط تعمل على الإطلاق.
تأكد من أن المجال الذي تقوم بالوصول إليه له اسم عادي (له فترة واحدة على الأقل ولا يحتوي على أحرف محظورة ، مثل الشرطات السفلية) وامسح ذاكرة التخزين المؤقت للمتصفح - وهما سببان رئيسيان لعدم عمل ملفات تعريف الارتباط.

إذا كان المثال من هنا يعمل ، لكن الكود الخاص بك لا يعمل ، فمن الواضح أن المشكلة ليست في الجلسات ، ولكن في الخوارزمية. ابحث عن المكان الذي فقدت فيه المتغير ، وانقل المثال من هنا خطوة بخطوة ، وصحح البرنامج النصي الخاص بك.

يمكن أن تنشأ مشكلة أخرى إذا كنت تستخدم إعادة توجيه الرأس أو التنقل عبر JavaScript.
الحقيقة هي أن PHP تقوم تلقائيًا بإلحاق معرف الجلسة فقط بروابط النموذج ، ولكن لا يتم إجراء ذلك مع العناوين وجافا سكريبت والعلامات الوصفية.
لذلك ، تحتاج إلى إضافة المعرف يدويًا ، على سبيل المثال ، مثل هذا:
header ("Location: /script.php؟". session_name (). "=". session_id ()) ؛

أيضًا ، نادر جدًا ، ومن غير الواضح تمامًا من أين تأتي المشكلة ، تكمن المشكلة في أن إعداد session.save_handler له قيمة أخرى غير الملفات. إذا لم يكن الأمر كذلك ، فقم بتصحيحه.

أمان
أمن الجلسة هو موضوع واسع. لذلك ، سأركز على بعض النقاط الرئيسية.
الشيء الأكثر شيوعًا في الكتب المدرسية هو عدم تمرير المعرف شريط العنوان... هذا مكتوب حتى في php.ini ، لكن هذا يحد من وظائف الجلسات. إذا قررت اتباع هذه النصيحة ، فبالإضافة إلى session.use_trans_sid = 0 ، لا تنسَ session.use_only_cookies = 1
يُنصح بربط الجلسة بعنوان IP: بهذه الطريقة ، إذا سُرق المعرّف ، فلن يتمكن الشرير من استخدامه في معظم الحالات.
يوصى باستخدام التوجيه session.save_path ، والذي يمكنك من خلاله ضبط دليلك الخاص لحفظ ملفات الجلسة. يعد هذا أكثر أمانًا مما لو تم تخزينها في الدليل المؤقت المشترك الافتراضي للخادم.

معلومة اضافية:

  • بالإضافة إلى ملفات تعريف الارتباط ، ترسل آلية الجلسة أيضًا رؤوسًا تمنع التخزين المؤقت للصفحة (نفس محدد ذاكرة التخزين المؤقت). بالنسبة لـ html ، هذا صحيح وضروري. ولكن عندما تحاول إرسال ملف باستخدام برنامج نصي يتحقق من الإذن ، يرفض Internet Explorer تنزيله. إنه بسبب هذا العنوان. يتصل
    session_cache_limiter ("خاصة") ؛
    يجب حل المشكلة قبل بدء الجلسة.
  • الغريب ، ولكن في الصفيف _SESSION دولارلا يمكنك استخدام المؤشرات الرقمية - $ _SESSION [1]، $ _SESSION ["10"]- الجلسات لن تعمل.
  • في مكان ما بين 4.2 و 5.0 لم يكن من الممكن تعيين session.use_trans_sid مع ini_set ()... بدءا من 5.0 فمن الممكن بالفعل مرة أخرى.
  • قبل الإصدار 4.3.3 ، أرسل ملف تعريف الارتباط PHP ملف تعريف الارتباط فقط إذا كان الطلب لا يحتوي على معرف في بداية الجلسة. الآن يتم إرسال ملف تعريف الارتباط في كل مكالمة بدء الجلسة ()

    مثال على إذن باستخدام الجلسات
    دعنا نوضح كل ما سبق بمثال صغير:
    لنقم بإنشاء ملف auth.php:
    if (isset ($ _ POST ["auth_name"]))
    {
    sql دولار = "حدد * من المستخدمين أين الاسم =؟ S";
    $ row = $ db -> getRow ($ sql، $ _POST ["auth_name"]) ؛
    إذا ($ row && password_verify ($ _POST ["auth_pass"] ، $ row ["pass"])) (
    $ _SESSION ["user_id"] = $ row ["id"] ؛
    }
    header ("الموقع: http: //". $ _SERVER ["HTTP_HOST"]. $ _SERVER ["REQUEST_URI"])؛
    خروج؛
    }

    if (isset ($ _ GET ["action"]) AND $ _GET ["action"] == "logout") (
    جلسة_ستارت () ،
    session_destroy () ،
    header ("الموقع: http: //". $ _SERVER ["HTTP_HOST"]. "/")؛
    خروج؛
    }

    إذا (! isset ($ _ SESSION ["user_id"])) (
    ?>








    خروج؛
    }

    الآن يكفي كتابة السطر في جميع البرامج النصية المحمية
    تتطلب "auth.php" ؛
    في هذا المثال ، من المفترض أن الجلسة قد بدأت بالفعل وأن الاتصال بقاعدة البيانات قد تم إنشاؤه باستخدام Class للعمل الآمن والمريح مع MySQL. يفترض أيضًا أنه تم تجزئة كلمة المرور باستخدام وظيفة password_hash الموصى بها.
    مثال على ملف محمي:

    جلسة_ستارت () ،
    تشمل "safemysql.class.php" ؛
    $ db = new safemysql (["db" => "test"])؛
    تشمل "auth.php" ؛
    ?>
    سر

    تسجيل خروج

    OPS! روابط مفيدة جدا:
    http://www.php.net/manual/ru/ref.session.php - أحدث وأحدث المعلومات حول دعم الجلسة في PHP في الوثائق الرسمية ، بالإضافة إلى العديد من تعليقات المستخدمين. يوصى بشدة بالقراءة.
    http://phpclub.ru/manrus/f/ref.session.html - ترجمة قديمة جدًا لهذا الفصل إلى اللغة الروسية ، من الوثائق التي ترجمها ألكسندر بيراميدين.
    http://phpclub.ru/detail/article/sessions
    مقال بعنوان طنان "حقيقة الجلسات". إنه يترك انطباعًا متناقضًا. في البداية ، يتحدث المؤلف عن آلية الجلسة بسهولة شديدة ، لكن الأساليب التي يقترحها في نهاية المقال موحلة تمامًا.

    مقال كتابي بقلم ديمتري بورودين من الموقع
    http://php.spb.ru/ غير مستحسن بشدة.
    يا رفاق ، لقد عفا عليها الزمن بشكل رهيب. لا يقتصر الأمر على عدم الدقة في الحقائق فحسب ، بل إن الجلسات في PHP ببساطة لم تُستخدم لفترة طويلة.
    شكراً جزيلاً لديما عليها ، كانت هذه أول مقالة عن الجلسات باللغة الروسية ، لقد درستها بنفسي ، لكنني الآن بحاجة إلى إرسالها إلى راحة مستحقة.
    أيضًا ، للأسف ، العديد من المقالات الأخرى الموجودة على الإنترنت والتي لم يتم تحديثها لسنوات أصبحت قديمة أيضًا.