أساسيات HttpSession
أساسيات HttpSession
HTTP بروتوكول عديم الحالة — يصل كل طلب وكأن الخادم لم يرَ هذا العميل من قبل قط. يحلّ حاوي servlet هذه المشكلة بواسطة HttpSession: خريطة تعيش على الخادم لتخزين السمات، مُفهرسةً بمعرّف جلسة فريد يُنقل إلى المتصفح على شكل كوكي (أو عبر إعادة كتابة URL حين تكون الكوكيز معطّلة). يغطّي هذا الدرس العمليات الثلاث الأساسية التي يجب أن يحفظها كل مطوّر servlet عن ظهر قلب: الحصول على جلسة، وكتابة السمات فيها، وقراءتها مجدّدًا، مع قواعد النطاق التي تحكم متى تكون تلك السمات مرئية.
الحصول على جلسة
نقطة الدخول هي طريقة واحدة على HttpServletRequest:
تتحكّم القيمة المنطقية في سياسة الإنشاء. استدعاء getSession() أو getSession(true) مناسب لتدفقات تسجيل الدخول وأيّ إجراء يُنشئ حالة المستخدم للمرة الأولى. استدعاء getSession(false) مناسب حين تريد التحقق من وجود جلسة دون إنشاء واحدة فارغة بالخطأ — كما في مرشّح أمان يحمي منطقة مقيّدة.
JSESSIONID=A3F9...)، ويخزّنه في ترويسة الاستجابة Set-Cookie، ويحتفظ بخريطة السمات في الذاكرة (أو في مخزن موزّع). في كل طلب لاحق يُعيد المتصفح تلك الكوكي ويبحث الحاوي عن الخريطة المقابلة.
تخزين سمات الجلسة
تضع HttpSession.setAttribute(String name, Object value) أيّ كائن قابل للتسلسل في خريطة الجلسة تحت مفتاح نصي. قد تبدو servlet تسجيل الدخول الواقعية كالتالي:
getSession(false) ثم invalidate() على الجلسة القديمة قبل إنشاء جلسة جديدة عند تسجيل الدخول. إن أعدت استخدام جلسة ما قبل تسجيل الدخول، فإن مهاجمًا زرع معرّف جلسة معروفًا في متصفح الضحية يحصل على الوصول بعد أن تتمّ عملية المصادقة.
قراءة سمات الجلسة
تُعيد HttpSession.getAttribute(String name) كائنًا من النوع Object (أو null إن كان المفتاح غائبًا). تُحوّله إلى النوع المتوقع:
بعض التفاصيل الجديرة بالملاحظة في هذا المقطع:
- يُستخدم
getSession(false)عن قصد — طلب GET على لوحة التحكم لا ينبغي أبدًا أن يُنشئ جلسة. - التحقق من null على كلٍّ من الجلسة والسمة يحمي من الجلسات المنتهية أو الملغاة يدويًا.
- التحويل النوعي (cast) حتمي لأن خريطة الجلسة تخزّن كائنات من النوع
Object. استخدام فئة مغلّفة ذات أنواع محدّدة (انظر النصيحة أدناه) يُزيل عمليات التحويل المتناثرة في قاعدة الكود.
إزالة السمات وإبطال الجلسة
عمليتان تُكمّلان دورة حياة السمة:
بعد استدعاء invalidate()، أيّ استدعاء إضافي على مرجع HttpSession ذاك يُطلق IllegalStateException. أعِد التوجيه دائمًا فورًا بعد الإبطال حتى لا تلمس الاستجابة الجلسة مجدّدًا.
نطاق الجلسة مقابل نطاق الطلب
فهم النطاقات يمنع الأخطاء الخفية. توجد أربعة نطاقات في تطبيق ويب Jakarta EE:
- نطاق الطلب (
request.setAttribute) — يعيش لدورة طلب/استجابة واحدة تمامًا. استخدمه لتمرير البيانات من servlet إلى JSP أثناءforward. - نطاق الجلسة (
session.setAttribute) — يعيش عبر طلبات متعددة من العميل ذاته حتى تنتهي مدة الجلسة أو تُبطَل. استخدمه لهوية المستخدم المصادق عليه وعربة التسوق وتفضيل اللغة. - نطاق التطبيق (
getServletContext().setAttribute) — مشترك بين جميع الجلسات وجميع العملاء طوال عمر تطبيق الويب. استخدمه للإعداد للقراءة فقط أو العدّادات العامة. - نطاق الصفحة (خاص بـ JSP فقط) — مقيّد بتنفيذ صفحة JSP واحدة.
getAttribute النيئة عبر servlets متعددة، غلّف الوصول إلى الجلسة في فئة مخصصة:
UserSession.get(session) — لا تحويلات نوعية، ولا سلاسل سحرية، وتغيير اسم المفتاح عملية من سطر واحد.
فحص الجلسة
تكشف HttpSession عن عدة طرق تشخيصية مفيدة في المرشّحات وصفحات الإدارة والتسجيل:
الخلاصة
واجهة الجلسة صغيرة لكن الانضباط في استخدامها بالغ الأهمية. استخدم getSession(false) كلما كنت تقرأ — لا تُنشئ جلسة كأثر جانبي للتحقق من وجودها. خزّن فقط ما يحتاج فعلًا إلى البقاء عبر الطلبات: هوية المستخدم المصادق عليه والتفضيلات ومحتوى عربة التسوق. ابقِ قيم السمات صغيرة وقابلة للتسلسل. وأبطِل الجلسة دائمًا ثم أعِد التوجيه عند تسجيل الخروج. في الدرس القادم سترى كيف يدير الحاوي عمر الجلسة من خلال إعداد المهلة وأحداث دورة الحياة.