class ActiveRecord::SessionStore::Session
The default Active Record class.
def self.find_by_session_id(session_id)
def self.find_by_session_id(session_id) find_by_sessid(session_id) end
def self.find_by_session_id(session_id)
def self.find_by_session_id(session_id) where(session_id: session_id).first end
def data
def data @data ||= self.class.deserialize(read_attribute(@@data_column_name)) || {} end
def data_column_size_limit
def data_column_size_limit @data_column_size_limit ||= columns_hash[data_column_name].limit end
def find_by_session_id(session_id)
def find_by_session_id(session_id) SEMAPHORE.synchronize { setup_sessid_compatibility! } find_by_session_id(session_id) end
def initialize(*)
def initialize(*) @data = nil super end
def loaded?
def loaded? @data end
def raise_on_session_data_overflow!
larger than the data storage column. Raises
Ensures that the data about to be stored in the database is not
def raise_on_session_data_overflow! unless loaded? throw :abort end limit = self.class.data_column_size_limit if limit and read_attribute(@@data_column_name).size > limit raise ActionController::SessionOverflowError end end
def secure!
on all existing sessions in the database. Users will not lose their session
To secure sessions created on those old versions, this method can be called
Sessions created on version <= 1.1.3 were guessable via a timing attack.
(see https://github.com/rack/rack/security/advisories/GHSA-hrqr-hxpp-chr3).
This method was introduced when addressing CVE-2019-16782
def secure! session_id_column = if self.class.columns_hash['sessid'] :sessid else :session_id end raw_session_id = read_attribute(session_id_column) if ActionDispatch::Session::ActiveRecordStore.private_session_id?(raw_session_id) # is already private, nothing to do else session_id_object = Rack::Session::SessionId.new(raw_session_id) update_column(session_id_column, session_id_object.private_id) end end
def serialize_data!
def serialize_data! unless loaded? throw :abort end write_attribute(@@data_column_name, self.class.serialize(data)) end
def session_id_column
def session_id_column 'session_id' end
def setup_sessid_compatibility!
def setup_sessid_compatibility! # Reset column info since it may be stale. reset_column_information if columns_hash['sessid'] def self.find_by_session_id(session_id) find_by_sessid(session_id) end define_method(:session_id) { sessid } define_method(:session_id=) { |session_id| self.sessid = session_id } else class << self; remove_possible_method :find_by_session_id; end def self.find_by_session_id(session_id) where(session_id: session_id).first end end end