إعادة كتابة URL وتتبّع الجلسات
إعادة كتابة URL وتتبّع الجلسات
HTTP بروتوكول عديم الحالة: كل طلب يقف بمفرده ولا يحتفظ الخادم بأي شيء بين الاستدعاءات. تمنح الجلسات وهمَ الاستمرارية، غير أنها تتطلب أن يتبادل المتصفح والخادم رمزًا مميزًا في كل طلب حتى يتمكّن الخادم من استرجاع كائن HttpSession الصحيح. الرمز المعياري ملف تعريف ارتباط (كوكي) يُسمّى JSESSIONID. لكن الكوكيز قد تُعطَّل — من قِبَل المتصفح أو المستخدم أو بروكسي مؤسسي. عند حدوث ذلك يلجأ الخادم إلى إعادة كتابة URL، بدمج الرمز المميز للجلسة مباشرةً في كل رابط وفي حقل action الخاص بكل نموذج، سواء كمعامل استعلام أو كجزء من مسار URL.
كيف يتتبّع الحاوية الجلسات
تُحدّد مواصفة Jakarta Servlet ثلاثة أوضاع لتتبّع الجلسات يمكن دمجها:
- COOKIE — تُعيّن الحاوية رأس الاستجابة
Set-Cookie: JSESSIONID=<token>; HttpOnly; Path=/مع أول استجابة، ويُعيد المتصفح إرساله تلقائيًا مع كل طلب لاحق. - URL — يُلحق الرمز المميز بعناوين URL على شكل
;jsessionid=<token>، مثال:/app/dashboard;jsessionid=ABC123. يعمل هذا حتى في حال حجب الكوكيز. - SSL — ترتبط الجلسة بمُعرِّف جلسة TLS (نادر الاستخدام عمليًا).
تُجري الحاوية التفاوض تلقائيًا: تُرسل الكوكي مع أول استجابة وتتحقق في الطلب التالي مما إذا كانت الكوكي قد عادت. إذا غابت الكوكي (إما لأنها لم تُرسل أصلًا أو حُذفت)، انتقلت إلى إعادة كتابة URL.
HttpServletResponse.encodeURL(String url) وHttpServletResponse.encodeRedirectURL(String url). إذا تيقّنت الحاوية أن العميل يقبل الكوكيز، تُعيد هذه الدوال عنوان URL دون تغيير. وإذا لم تتأكد من ذلك أو كانت الكوكيز غائبة، تُلحق ;jsessionid=.... استدعِهما دومًا — في أسوأ الحالات يكونان بلا أثر.
encodeURL في التطبيق العملي
يجب تغليف كل رابط تشعّبي وكل حقل action لنموذج في صفحة يُصيّرها الخادم باستدعاء encodeURL:
حين تكون الكوكيز مفعّلة يكون الناتج ببساطة /app/profile. حين تكون الكوكيز معطّلة يصبح الناتج /app/profile;jsessionid=A7F3D2C1B8E94560. يبقى HTML متطابقًا في الحالتين — كودك يظل متكيّفًا مع كلا الوضعَين.
عمليات إعادة التوجيه تحتاج encodeRedirectURL
encodeURL مخصّصة للروابط داخل HTML، أما encodeRedirectURL فهي لرأس Location الذي يُرسَل مع إعادة التوجيه. استخدم الدالة المناسبة في سياقها الصحيح:
req.getContextPath() عند بناء عناوين URL. الترميز المباشر لمسار مثل /app/... يُخطئ فور نشر التطبيق تحت جذر سياق مختلف. تُعيد getContextPath() البادئة الصحيحة — سلسلة فارغة للنشر في الجذر، و/myapp في غير ذلك.
إعداد وضع تتبّع الجلسة
يمكنك تقييد أوضاع التتبّع أو التحكم فيها عبر web.xml لفرض سياسة أمنية:
أو برمجيًا أثناء تهيئة التطبيق:
Referer المُرسَل إلى مواقع الطرف الثالث، وسجلات وصول الخادم، والإشارات المرجعية المشتركة. في معظم تطبيقات الإنتاج ينبغي فرض تتبّع الكوكيز فقط مع اشتراط HTTPS، مما يجعل الرمز المميز غير مرئي خارج القناة المشفّرة.
JSP و JSTL: الوسم c:url يتكفّل بالمهمة
حين تكتب الواجهات بلغة JSP، يستدعي وسم JSTL <c:url> الدالةَ encodeURL داخليًا تلقائيًا دون أن تحتاج إلى التذكّر:
هذا أحد الأسباب التي تجعل واجهات JSP/JSTL مُفضَّلة على بناء HTML يدويًا في كود السيرفلت — يُعالَج الإسهاب المتعلق بإدارة الجلسة بشفافية تامة.
كيف تُحلَّل معرّفات الجلسة القادمة في الحاوية
مع كل طلب وارد، تُشغّل request.getSession() (ومتغيراتها) التسلسل الداخلي الآتي:
- فحص رأس
Cookieبحثًا عنJSESSIONID. - إن لم يوجد، فحص URI الطلب بحثًا عن
;jsessionid=<token>. - البحث عن الرمز المميز في مخزن الجلسات (الذاكرة، قاعدة البيانات، Redis، إلخ).
- إعادة
HttpSessionإن وُجد ولم تنته صلاحيته؛ وإلا إنشاء جلسة جديدة (في حالةgetSession(true)) أو إعادةnull(في حالةgetSession(false)).
يمكنك معرفة الآلية التي أوصلت الجلسة الحالية:
الخلاصة
إعادة كتابة URL هي آلية الاحتياط في حاوية السيرفلت لضمان استمرارية الجلسة حين تكون الكوكيز غير متاحة. الدالتان الأساسيتان هما encodeURL للروابط التشعّبية وencodeRedirectURL لاستجابات إعادة التوجيه — استدعِهما دومًا حتى يعمل تطبيقك في كلا بيئتَي الكوكيز وانعدامها. في الإنتاج، فرض تتبّع الكوكيز فقط مع علامتَي HttpOnly وSecure يُبعد رموز الجلسات عن السجلات وسجل المتصفح. وحين تكتب واجهات JSP، دع <c:url> يتولّى التشفير عنك.