我知道一旦访问会话,会话 ID 由
铁轨。听说如果修改了一个session,rails有一个版本
在会话上盖章。
通过阅读ActionDispatch::Session::CookieStore的源代码可以很容易地验证这个说法是错误的。
# frozen_string_literal: true
require "active_support/core_ext/hash/keys"
require "action_dispatch/middleware/session/abstract_store"
require "rack/session/cookie"
module ActionDispatch
module Session
# ... comments truncated for readibility
class CookieStore < AbstractStore
def initialize(app, options = {})
super(app, options.merge!(cookie_only: true))
end
def delete_session(req, session_id, options)
new_sid = generate_sid unless options[:drop]
# Reset hash and Assign the new session id
req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid } : {})
new_sid
end
def load_session(req)
stale_session_check! do
data = unpacked_cookie_data(req)
data = persistent_session_id!(data)
[data["session_id"], data]
end
end
private
def extract_session_id(req)
stale_session_check! do
unpacked_cookie_data(req)["session_id"]
end
end
def unpacked_cookie_data(req)
req.fetch_header("action_dispatch.request.unsigned_session_cookie") do |k|
v = stale_session_check! do
if data = get_cookie(req)
data.stringify_keys!
end
data || {}
end
req.set_header k, v
end
end
def persistent_session_id!(data, sid = nil)
data ||= {}
data["session_id"] ||= sid || generate_sid
data
end
def write_session(req, sid, session_data, options)
session_data["session_id"] = sid
session_data
end
def set_cookie(request, session_id, cookie)
cookie_jar(request)[@key] = cookie
end
def get_cookie(req)
cookie_jar(req)[@key]
end
def cookie_jar(request)
request.cookie_jar.signed_or_encrypted
end
end
end
end
如您所见,persistent_session_id! 会覆盖现有的会话 ID cookie。它不跟踪以前的 sid。对于会话、memcached (dalli) 和 ActiveRecord 等其他存储,似乎并没有明显删除 sid,但没有您想象的那种“版本控制”api。
如果您想拥有此功能,您可以将中间件堆栈中的 ActionDispatch::Session::CookieStore(或您正在使用的任何存储)与您自己的会话中间件交换。
对于您正在做的任何事情,可能有一个更简单的解决方案,但如果它是常见的东西,例如存储用户登录次数(将其存储在数据库中)或页面浏览量(使用谷歌分析或数据库)或您有什么.此外,如果您正在做的任何事情都需要版本化 - 它真的应该首先在会话中吗?