جلسات ملفات تعريف الارتباط في Discourse (خطأ 400: حجم رأس الطلب أو ملف تعريف الارتباط كبير جدًا)

لماذا تمتلك Discourse ملفات تعريف ارتباط (cookies) كبيرة جداً؟ هل هناك سبب لذلك؟ وهل توجد طريقة لتقليل حجمها؟

كنت أتصفح لوحة تحكم المشرف في Discourse، وفجأة حصلت على خطأ 400 Bad Request من /sidekiq/retries

400 Bad Request
Request Header Or Cookie Too Large

تحققت من الطلب وتأكدت من أن متصفحي أرسل رأس Cookie ضخمًا إلى خادم Discourse. لماذا؟

Cookie: _t=403b8203003bdaf522679e0b6c17605f; rack.session=BAh7C0kiD3Nlc3Npb25faWQGOgZFVG86HVJhY2s6OlNlc3Npb246OlNlc3Np%0Ab25JZAY6D0BwdWJsaWNfaWRJIkU4NjY1Y2Y3MjU4OGYzZjk3MDUyMDdhNzhh%0ANzc4OGZlZTRhNzFkY2JjMzA4NDAyNjY3MWMwNmFhYzc2Zjg0NWIyBjsARkki%0AEF9jc3JmX3Rva2VuBjsARkkiMW9KNk83S1B5ZUVaR0I2WnBxckxISzNxbEla%0AdGRyVXNCUnc3d2JiaVorVmM9BjsARkkiFnNlY3VyZV9zZXNzaW9uX2lkBjsA%0AVEkiJWM3YWJjYTk3OTRlNTExNTllZWUyMTBkYmVkNDgzNDc4BjsARkkiCmZs%0AYXNoBjsAVHsHSSIMZGlzY2FyZAY7AFRbAEkiDGZsYXNoZXMGOwBUewZJIgxy%0AZWZlcmVyBjsAVCJPaHR0cHM6Ly9kaXNjb3Vyc2Uub3BlbnNvdXJjZWVjb2xv%0AZ3kub3JnL3UvbWFsdGZpZWxkMC9tZXNzYWdlcy9ncm91cC9hZG1pbnNJIglj%0Ac3JmBjsARkkiMVRuUHJ6TTMzUHZqcG9oditwdTRyem9HeDUxQnAwL0psci9z%0AYkFZWkpxdkU9BjsARkkiDXRyYWNraW5nBjsARnsGSSIUSFRUUF9VU0VSX0FH%0ARU5UBjsAVEkiLTk3MDJkMjYxMmJlZmM5N2U4YTIzMDVkNjU0Y2IwOThmMmQ4%0AYTI1NTUGOwBG%0A--e602081dddcd88bdb269034e7acb8c582665be0e; _forum_session=V2dWY0FGVGhsMDVtcmdmNVdicXpJVkxnVC9vUWpkeVdpSHRIYWZaVVhVZDUxcFlRdTh4bHFTQVRRcUpGR3pMRGZ1M3NGeENzUloreGdEWEtQS2Z2WDJKNFZUeXRjNXlTTTRHVzJsQzBORzVuSW9NNHg3UHhwNzdUNFlCNGVvcytkSjA1b0d3NlM3czNlTlFxMEloQmNOYzMxTm5mYW4zaWlMSkpxWXZiZDlBRFJnR3dxTkphM0ZtZmk4bGswcUdzYm94b3pkUk0zTG5sMjhqNkxYMnZqMjJPYkhzMGFLM2JWZzBCRXpFa2wyZm1HbUl3REVzd3c5MmhRMG5YMkFJV0t6Z2ZPRlI2bVpOQWJlZWJQd2pyclEvdmVmWUlsYkxyU0EzcDFaZkRpOU14SVptMk01TjZtZlNXa2VUQnFaaGZpNDlaQVBnY0RCS2ZlbVBiQWt3S2lSeHcvY0g2WUlXOTRLejh2dVhhcDFoRXVobUdRMnJvcjhtRTkxZjZCYXM1eDd2NU1rZ3duRy83VVhVSG5Ua3BIOTJoQ1orY2dlMjh2M0Fuc0lwb3p3ckVtaXhxaDkxT2E1YnEvbnBWTVlCaXd4Q2h6eTd5Ty84WUYzeUVFbE9KSXhadXZ4aUw1TmVoSEE0cW9YSHA3VTJoK3NtdktrL09qcDVxMnR5bFhhUmU1dDMzT0ZBUGxBRXBZVHB5WlNtODM2YzBsOVRkc3RpMmFFSW5COEhyRjFTY2ZCZk5VbUpYN2JzYlh6SGNGWEs2dWhQUkJnMmd4K3ZJQUFkQThwa2tOMnI3Vi9qMFo5RE5XWWxxRXFTTTNmRnJKU294aStKZFJ4NHRDTGh4WXR1Z3F5QWU3ZkMxTXBpMzcvYTd5QkRwajNjcDF6SWdFSkdqNDJlMk0vYW1mODNEdDhZSk9jbzRPRHNhZUYzNjVOWkErbVJSNG82VnhRL0FFRUtWbE1uQWFPa0JqQUFmZ21iL0YvSFIrM1dlSDNvPS0tK1pMRzNmRjA4L3c4VTkrVEllYmNQZz09--325ca2e886afaefffeb6174c99776f91fefd4292

سلسلة ملفات تعريف الارتباط في Discourse أعلاه يبلغ طولها 1,962 حرفًا!

للمقارنة، فإن رأس الكوكي المُرسل إلى موقع Mediawiki الخاص بي يبلغ طوله 122 حرفًا فقط، متضمنًا اسم المستخدم ومعرف المستخدم ومعرف الجلسة.

معرف الجلسة في Mediawiki يبلغ طوله 32 حرفًا، لكن Discourse يبدو أنه يحتوي على معرفي جلسة: rack.session يبلغ طوله 813 حرفًا و _forum_session يبلغ طوله 1,075 حرفًا. يرجى مساعدتي في فهم سبب حاجة معرف مستخدم بسيط (uid) لأن يكون بهذه الطول. هل يمكنني تكوين Discourse لاستخدام معرف جلسة أقصر؟ هل مثل هذا الطلب منطقي؟

ما الذي يُخزن في هذه السلسلة؟ هل من الممكن جعلها أصغر؟

على وجه التحديد، لأي مكون من مكونات برنامج Discourse يُستخدم rack.session؟ وماذا يُستخدم _forum_session؟

بالتأكيد يمكنني مجرد رفع حدود تكوين nginx، لكنني أود الحفاظ عليها منخفضة بشكل معقول ما لم يكن هناك شرط قوي لزيادتها.

أنا مؤيد لمراجعة ملفات تعريف ارتباط الجلسة لدينا، وربما الانتقال إلى استخدام افتراضي لجلساتنا المدعومة بـ Redis والتي تنتهي تلقائيًا، وهو أمر أفضل على أي حال. @david، هل لديك أي أفكار في هذا الصدد؟

هذا لا ينبغي أن يكون مشكلة لشخص يستخدم تثبيتنا الرسمي، فقط للأشخاص الذين يستخدمون وكلاء سيئة التكوين، أليس كذلك؟

كما أن ضغط رؤوس HTTP/2 يجعل هذه الرؤوس تُحمّل مرة واحدة فقط طوال زيارة المستخدم.

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

يا إلهي، تم هذا الضبط عمدًا لأغراض أمنية؛ إنه ليس “وكيلًا سيئ التكوين”. إن تخفيض القيم التالية في أوامر nginx يُعد إجراءً شائعًا ضمن إجراءات تعزيز أمان nginx (لمعالجة التوافر، وتحديد المعدلات، ومنع هجمات حجب الخدمة، إلخ):

limit_conn_zone
limit_conn
limit_req_zone
client_body_timeout
client_header_timeout
ssl_*
add_header # SAMEORIGIN/XSS-Protection/CORS/CSP
client_body_buffer_size
client_header_buffer_size
large_client_header_buffers
client_max_body_size

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

شكرًا لك يا سام. هل تقصد بـ “الانتقال إلى استخدام افتراضي لـ Redis” أن من الممكن حاليًا نقل البيانات المخزنة في ملف تعريف ارتباط الجلسة إلى Redis عن طريق تغيير في التكوين؟ أم أن نقل هذه البيانات من ملف تعريف ارتباط الجلسة إلى الخادم سيتطلب حتمًا تغييرًا في الكود؟

لا، يتطلب ذلك تغييرًا في الكود.

لماذا يُعدّ وجود 10 آلاف رأس مشكلة؟ فهي مضغوطة، وإذا كان وجود 10 آلاف رأس مشكلة، فلماذا يُسمح بحمولة HTML بحجم 10 آلاف؟

ملاحظة: اضطررت أيضًا إلى تجاوز تعليمات large_client_header_buffers في إعدادات nginx المشددة الخاصة بي لكي يعمل Discourse بشكل صحيح.

على وجه التحديد، أستخدم large_client_header_buffers 2 1k في إعدادات nginx لجميع مواقع أخرى. لكن هذا يتسبب في ظهور خطأ 414 Request-URI Too Large من /admin/reports/bulk?XYZ — حيث أن XYZ يتكون فعليًا من 1,019 حرفًا!

تم حل هذه المشكلة عن طريق ضبط large_client_header_buffers 4 8k; في كتلة server{} الخاصة بإعدادات nginx الخاصة بـ Discourse، مما يتجاوز التعليمات العامة ويعيد القيمة الافتراضية لهذه التعليمات لـ Discourse.

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

هذه حالة استخدام محدودة للغاية… خاصة بالمسؤولين.

بالنسبة لشخص ليس مهندس الواجهة الخلفية، ما هو الحل لهذه المشكلة؟

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

نقدر أي نصيحة حول إصلاح هذا لنسختنا من Discourse.

هل يمكنك ربط مثال؟ هذه المشكلة في OP تتعلق باستضافة Discourse ذاتيًا، لذلك لا أفهم كيف يمكن أن تؤثر على مثيل مستضاف مثل الذي ربطته.