Rails 4 升级 JSON::ParseError 旧会话
Posted
技术标签:
【中文标题】Rails 4 升级 JSON::ParseError 旧会话【英文标题】:Rails 4 upgrade JSON::ParseError for old sessions 【发布时间】:2014-09-21 19:25:31 【问题描述】:从 Rails 3.2 升级到 Rails 4.1.4 后,使用现有会话(从旧的 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'
...
我尝试更改会话 cookie 密钥名称,但它似乎卡在 session_id
。
# initializers/session_store.rb
MyApp::Application.config.session_store :cookie_store, key: 'myapp_session'
请帮忙!一个很好的解决方案是在所有会话 cookie 碰到 rails 中间件之前删除它们,但我不知道该怎么做..
【问题讨论】:
【参考方案1】:在这里找到答案: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
这样就成功了
【讨论】:
我怀疑如果稍后您切换到 :json 并且很久以前没有访问您的应用程序的人回来时会发生同样的错误。想知道如何处理这种情况!也许改变秘密就足够了,不确定。 我认为hybrid
序列化程序的重点是解决您描述的场景。
澄清:我担心(但会验证)长期保持混合激活会留下安全问题,因为可以传递 yaml 等。如果这是真的,切换到 :json而不是 :hybrid 在某些时候会是一个好主意,否则它会完全违背目的。我关心的是如何在切换到 :json 时避免错误 500,并且有旧 cookie 的人进来了。我会玩弄并调查以了解这部分。
@ThibautBarrère 我刚刚在将 cookies_serializer 设置为 :json 时遇到了这个问题。尽管我的浏览器有一个旧的会话 cookie,但我更改了我的密码并且它运行良好,没有 500 错误。
如果您可以更改密码,则无需使用混合。【参考方案2】:
我只是遇到了同样的问题,并在这里使用了答案,一切都已解决。 在阅读了 cmets 之后,我发现只是更改密码也解决了问题,正如我所想的那样。
我认为更改秘密比切换到 :hybrid 更好,如 cmets 中所述的@Thibaut Barrère
【讨论】:
【参考方案3】:如果您对更改密钥感到满意,那么它将解决问题,我可以确认使用旧 cookie 的人不会遇到 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
我可以确认这有效,即使您的浏览器存储了旧的会话 cookie。通过更改密钥,当具有旧会话 cookie 的人访问您的站点时,服务器会简单地忽略旧会话状态并创建一个新会话。没有 500 错误。
【讨论】:
以上是关于Rails 4 升级 JSON::ParseError 旧会话的主要内容,如果未能解决你的问题,请参考以下文章
将 Bundler 升级到 2.1.4 后初始化 Rails 控制台出错