我有一个 Rails 应用程序,它使用 Devise 和 activerecord-session_store gem 以及简约的设置(没有超出默认值)。
我正在尝试使用存储在cookie中的值来手动查找activerecord-session_store使用的
sessions
表中相应的会话记录。
问题是我从 cookie 获取的会话值似乎没有“按原样”存储在数据库中,因此我不能简单地执行 find_by 来查找它匹配的记录。
或者换句话说:
cookie 值如下所示: a5a879b4f923d2eea7707cf8ce28cd80
这就是
session_id
表中的 sessions
的样子:
2::801e4371783f192b4ee95be9def08bf17daaa1ebeed589dbdfeeb8742e2dd9f6
sessions
表中的值似乎以某种方式加密,我找不到有关如何匹配两者的信息。
值得指出的是,该应用程序工作正常,因此它以某种方式在内部进行匹配。我正在尝试为不同的用例匹配 session_id。
我尝试使用
find_by_session_id
公开的 ActiveRecord::SessionStore::Session
方法,希望它能进行一些转换并神奇地找到正确的会话,但它似乎只是活动记录中的标准 find_by ,由于字符串值不同,因此不起作用.
我的猜测是,我需要以某种方式将来自 cookie 的值转换为保存在 session_id 列中的格式数据,然后才执行 find_by 但我不知道如何。
您知道如何使用 cookie 值找到正确的会话吗?谢谢
虽然我无法提供有关其工作方式和原因的详细信息,但我找到了解决方案:
首先,需要根据 cookie 值生成一个 private_session_id,然后才能调用
find_by_session_id
。
类似这样的:
private_session_id = Rack::Session::SessionId.new(COOKIE_VALUE).private_id
ActiveRecord::SessionStore::Session.find_by_session_id(private_session_id)
只是想为之前的答案做出更多贡献,因为我自己对这个问题很好奇。
有关更多详细信息,请访问 activerecord-session_store gem 源代码,您可以在其中找到处理我们正在讨论的内容的
Rack::Session::SessionId
类。
要使其工作,需要在对象初始化期间传递从 cookie 获取的
public_id
。在类中,有一个常量 ID_VERSION
设置为 2。
私有方法
hash_sid
采用字符串作为输入并返回64个字符的十六进制值:
def hash_sid(sid)
Digest::SHA256.hexdigest(sid)
end
然后,有一个名为
private_id
的方法,它会为您提供一个与数据库记录中存储的 session_id
相匹配的字符串:
def private_id
"#{ID_VERSION}::#{hash_sid(public_id)}"
end
您可以根据您的实现使用以下任一查询:
ActiveRecord::SessionStore::Session.find_by_session_id(private_id)
或
Session.find_by(session_id: private_id)