الجلسةُ التي تختفي تبدو مشكلةَ دخول، ولا تكاد تكون كذلك أبدًا. فالدخولُ نجح، وضاع دليلُه بين طلبٍ والذي يليه.

١. شيءٌ ينظّف ملفّات الجلسات

على دبيان وأوبونتو يكنس مؤقّتٌ ملفّاتِ جلسات PHP على جدولٍ خاصٍّ به، بمفهوم التوزيعة للعمر لا بالمفهوم الذي تضبطه صفحتُك بـ ini_set. فصفحةٌ ترفع gc_maxlifetime في وقت التشغيل لا تغيّر من ذلك الكنس شيئًا.

systemctl list-timers | grep phpsessionclean
php -i | grep -E "session.save_path|session.gc_maxlifetime"

والعلاجُ دليلُ جلساتٍ خاصٌّ بك لا يمسّه الكانس، وعمرُه مضبوطٌ في إعداد الحوض لا في وقت التشغيل.

php_admin_value[session.save_path] = /var/lib/php/sessions-mysite
php_admin_value[session.gc_maxlifetime] = 86400

٢. الكعكة لا تعود

session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
الإعداد cookie_secure على موقعٍ يُبلَغ عبر http الصريح معناه أنّ الكعكة لا تُعاد أبدًا، فيخرج المستخدم في الحال بلا خطأٍ في أيّ مكان. وهو صوابٌ على موقع https خالص، وقاتلٌ على موقعٍ مختلط.

٣. خادمان وجلسةٌ واحدة

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

  • الجلساتُ في Redis أو في قاعدة البيانات، يتشاركها الخادمان.
  • أو جلساتٌ لاصقة عند الموزّع، وهي تنجح ولا تنجو من استبدال خادم.

راقب الأمر وهو يقع

ls -la /var/lib/php/sessions/ | head
# log in, then look again: your file should be there and should stay
فإن كان الملفُّ موجودًا والمستخدم خارجٌ مع ذلك فالسببُ الكعكة. وإن اختفى الملفّ فالسببُ الكانس. وتلك الملاحظةُ وحدها تشقّ المشكلة نصفين.