يقوم Rails 4 بترقية JSON::ParseError للجلسات القديمة
-
21-12-2019 - |
سؤال
بعد الترقية إلى Rails 4.1.4 من Rails 3.2، يؤدي الوصول إلى التطبيق بجلسة موجودة (من إصدار Rails 3.2 الأقدم) إلى حدوث خطأ داخلي في الخادم.أثر خلفي:
JSON::ParserError - 795: unexpected token at {
I"session_id:ETI"%fa78a4ee07ac952c9b034ebc6199f30b;':
/Users/.../.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/json/common.rb:155:in `parse'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:388:in `load'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:428:in `deserialize'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:183:in `verify_and_upgrade_legacy_signed_message'
actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:550:in `[]'
actionpack (4.1.4) lib/action_dispatch/middleware/session/cookie_store.rb:114:in `get_cookie'
actionpack (4.1.4) lib/action_dispatch/middleware/session/cookie_store.rb:90:in `block in unpacked_cookie_data'
actionpack (4.1.4) lib/action_dispatch/middleware/session/abstract_store.rb:51:in `stale_session_check!'
actionpack (4.1.4) lib/action_dispatch/middleware/session/cookie_store.rb:89:in `unpacked_cookie_data'
actionpack (4.1.4) lib/action_dispatch/middleware/session/cookie_store.rb:83:in `block in extract_session_id'
actionpack (4.1.4) lib/action_dispatch/middleware/session/abstract_store.rb:51:in `stale_session_check!'
actionpack (4.1.4) lib/action_dispatch/middleware/session/cookie_store.rb:82:in `extract_session_id'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:49:in `block in []'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:48:in `[]'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:70:in `id'
rack (1.5.2) lib/rack/session/abstract/id.rb:282:in `current_session_id'
rack (1.5.2) lib/rack/session/abstract/id.rb:288:in `session_exists?'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:152:in `exists?'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:172:in `load_for_read!'
actionpack (4.1.4) lib/action_dispatch/request/session.rb:89:in `[]'
warden (1.2.3) lib/warden/session_serializer.rb:30:in `fetch'
warden (1.2.3) lib/warden/proxy.rb:212:in `user'
warden (1.2.3) lib/warden/proxy.rb:318:in `_perform_authentication'
warden (1.2.3) lib/warden/proxy.rb:104:in `authenticate'
warden (1.2.3) lib/warden/proxy.rb:114:in `authenticate?'
devise (3.2.4) lib/devise/rails/routes.rb:460:in `block in constraints_for'
actionpack (4.1.4) lib/action_dispatch/routing/mapper.rb:38:in `block in matches?'
actionpack (4.1.4) lib/action_dispatch/routing/mapper.rb:36:in `matches?'
actionpack (4.1.4) lib/action_dispatch/routing/mapper.rb:45:in `call'
actionpack (4.1.4) lib/action_dispatch/journey/router.rb:71:in `block in call'
actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in `call'
actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:678:in `call'
...
لقد حاولت تغيير اسم مفتاح ملف تعريف الارتباط للجلسة، ولكن يبدو أنه عالق session_id
.
# initializers/session_store.rb
MyApp::Application.config.session_store :cookie_store, key: 'myapp_session'
الرجاء المساعدة!سيكون الحل الرائع أيضًا هو حذف جميع ملفات تعريف الارتباط الخاصة بالجلسة قبل أن تصل إلى البرامج الوسيطة لـ Rails، لكن ليس لدي أي فكرة عن كيفية القيام بذلك..
المحلول
وجدت الجواب هنا: https://github.com/rails/rails/issues/15111
إعداداتي كانت
# initializers/cookie_serializer.rb
Rails.application.config.action_dispatch.cookies_serializer = :json
لقد غيرته إلى
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
هذا أدى الغرض
نصائح أخرى
إذا كنت مرتاحًا لتغيير مفتاحك السري، فسوف يحل المشكلة، ويمكنني أن أؤكد أن الأشخاص الذين لديهم ملفات تعريف ارتباط قديمة لن يواجهوا خطأ 500.
يجري rake secret
لتوليد سر جديد.
إذا كنت قد نفذت config/secrets.yml
, ، ضع السر الجديد هناك.وإلا، إذا كان لا يزال لديك سرك config/initializers/secret_token.rb
, ، ضعه هناك.
اترك خاصتك config/initializers/session_store.rb
الملف وحده - لا تحتاج إلى تغييره.
في config/initializers/cookie_store.rb
, ، تغييره إلى :json
:
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json
أستطيع أن أؤكد أن هذا يعمل، حتى عندما يقوم متصفحك بتخزين ملف تعريف ارتباط جلسة قديمة.من خلال تغيير السر، عندما يقوم شخص لديه ملف تعريف ارتباط جلسة قديمة بزيارة موقعك، يتجاهل الخادم ببساطة حالة الجلسة القديمة ويقوم بإنشاء جلسة جديدة.لا يوجد 500 خطأ.
لقد واجهت نفس المشكلة واستخدمت الإجابة هنا وتم إصلاح كل شيء.بعد قراءة التعليقات وجدت أن مجرد تغيير السر أدى أيضًا إلى حل المشكلة، كما ينبغي أن أفترض.
أعتقد أن تغيير السر هو حل أفضل للمشكلة من التبديل إلى :hybrid كما ذكر @Thibaut Barrère في التعليقات