我是 Rails 新手,遇到了一个我不明白的奇怪问题。我使用 ActiveRecord 作为会话存储,并且需要将会话 ID 添加为所有请求的 JSON 响应的属性。如果它对情况有一些影响,我也会使用 Devise。问题是,如果用户发出的请求没有 cookie(或至少 cookie 中没有会话 id),则 session.id 为空或 - 请注意 - 与响应 cookie 中设置的值不同。
为了调试,我将此代码作为 after_filter 添加到 ApplicationController:
puts session.id
puts request.session_options[:id]
两个值相同。它们匹配 cookie 中的值(如果存在)。否则,如果 cookie 中不存在会话 ID,则在该请求之后设置的 cookie 具有不同的值。
我的观点是 session_id 在实际保存到数据库后会获得新值,它必须是唯一的。数据库迁移:
def change
create_table :sessions do |t|
t.string :session_id, :null => false
t.text :data
t.timestamps
end
add_index :sessions, :session_id, :unique => true
add_index :sessions, :updated_at
end
我的问题:如何在呈现第一个响应之前获取新会话的实际 session.id 值?
升级版:
我刚刚创建了一个新的 Rails 应用程序,它使用 ActiveRecord 会话存储而不使用 Devise,并且我可以在使用此代码 id 应用程序控制器响应之前获取将在 cookie 中设置的 session.id:
class ApplicationController < ActionController::Base
after_filter :show_session
def show_session
puts session.id
end
end
但是在我现有的带有 Devise 的应用程序中,我得到了一个看起来像会话 ID 的值,但这与通过 Set-Cookie 响应标头在 cookie 中设置的值以及实际保存到数据库中会话表的值不匹配。看起来 Devise 在某种程度上与 ActiveRecord 会话存储有冲突。需要更深入地弄清楚。
更新 2
看起来我找到了问题的根源。正如我所说,我使用 Devise 来获得 Omniauth 的授权。根据文档,出于安全原因,sign_in 方法会重置会话 ID。但在重置 session.id 之后,它会返回自动设置的旧值。我将此代码用作 Omniauth 回调:
def facebook_access_token
sign_in @user
puts session.id
end
在控制台中,我得到的会话 ID 与 Set-Cookie 响应标头中的设置不同。如果我评论“sign_in”行,这些值匹配。新问题:在 sign_in 方法中重置后如何获取新的会话 id 值?它是内部 Warden/Devise 实施还是什么?