Spec-Zone.ru › Ruby 3.2

class CGI::Session

Parent:
Object

Обзор

Этот файл предоставляет класс CGI::Session, который обеспечивает поддержку сессий для скриптов CGI. Сессия — это последовательность HTTP-запросов и ответов, связанных вместе и ассоциированных с одним клиентом. Информация, связанная с сессией, хранится на сервере между запросами. Идентификатор сессии передаётся между клиентом и сервером с каждым запросом и ответом, прозрачно для пользователя. Это добавляет информацию о состоянии в протокол HTTP-запроса/ответа, который по своей природе бессостоятелен.

Жизненный цикл

Экземпляр CGI::Session создаётся из объекта CGI. По умолчанию этот экземпляр CGI::Session начнёт новую сессию, если текущая сессия отсутствует, или продолжит текущую сессию для этого клиента, если она существует. Опция new_session может быть использована для того, чтобы всегда или никогда не создавать новую сессию. Подробнее см. в new().

delete() удаляет сессию из хранилища сессий. Однако это не удаляет идентификатор сессии из клиента. Если клиент отправляет ещё один запрос с тем же идентификатором, то это приведёт к началу новой сессии с идентификатором старой сессии.

Установка и получение данных сессии.

Класс Session ассоциирует данные с сессией в виде пар «ключ-значение». Эти данные могут быть установлены и получены путем индексирования экземпляра Session с использованием «[]», аналогично хэшам (хотя другие методы работы с хэшами не поддерживаются).

После завершения обработки сессии для запроса сессия должна быть закрыта с помощью метода close(). Это позволит сохранить состояние сессии в постоянном хранилище. Если вы хотите сохранить состояние сессии в постоянном хранилище без завершения обработки сессии для этого запроса, вызовите метод update().

Хранение состояния сессии

Вызывающий код может указать тип хранилища для данных сессии с помощью опции database_manager для CGI::Session::new. Следующие классы хранилищ предоставляются в стандартной библиотеке:

CGI::Session::FileStore

хранит данные как обычный текст в плоском файле. Работает только с данными String. Это тип хранилища по умолчанию.

CGI::Session::MemoryStore

хранит данные в хэше в оперативной памяти. Данные сохраняются только до тех пор, пока существует текущая инстанция интерпретатора Ruby.

CGI::Session::PStore

хранит данные в формате Marshal. Предоставляется файлом cgi/session/pstore.rb. Поддерживает данные любого типа и обеспечивает блокировку файлов и поддержку транзакций.

Пользовательские типы хранилищ также могут быть созданы путём определения класса с указанными методами:

new(session, options)
restore  # returns hash of session data.
update
close
delete

Изменение типа хранилища во время сессии не работает. Обратите внимание, что по умолчанию файлы данных сессии FileStore и PStore имеют одинаковое имя. Если ваше приложение переключается с одного типа на другой, не убедившись, что имена файлов будут разными, и клиенты по-прежнему будут иметь старые сессии в куках, то всё сломается!

Поддержание идентификатора сессии.

Большая часть состояния сессии хранится на сервере. Однако идентификатор сессии должен передаваться туда и обратно между клиентом и сервером для поддержания ссылки на это состояние сессии.

Самый простой способ сделать это — через куки. Класс CGI::Session обеспечивает прозрачную поддержку связи идентификатора сессии через куки, если у клиента включены куки.

Если у клиента отключены куки, идентификатор сессии должен быть включен в качестве параметра всех запросов, отправляемых клиентом серверу. Класс CGI::Session в сочетании с классом CGI прозрачно добавит идентификатор сессии как скрытое поле ввода во все формы, сгенерированные с помощью метода HTML-генерации CGI#form(). Не предусмотрена встроенная поддержка других механизмов, таких как переписывание URL. Вызывающий код отвечает за извлечение идентификатора сессии из атрибута session_id и ручное его кодирование в URL и добавление в скрытые поля ввода HTML-форм, созданных другими механизмами. Также истечение срока действия сессии не обрабатывается автоматически.

Примеры использования

Установка имени пользователя

require 'cgi'
require 'cgi/session'
require 'cgi/session/pstore'     # provides CGI::Session::PStore

cgi = CGI.new("html4")

session = CGI::Session.new(cgi,
    'database_manager' => CGI::Session::PStore,  # use PStore
    'session_key' => '_rb_sess_id',              # custom session key
    'session_expires' => Time.now + 30 * 60,     # 30 minute timeout
    'prefix' => 'pstore_sid_')                   # PStore option
if cgi.has_key?('user_name') and cgi['user_name'] != ''
    # coerce to String: cgi[] returns the
    # string-like CGI::QueryExtension::Value
    session['user_name'] = cgi['user_name'].to_s
elsif !session['user_name']
    session['user_name'] = "guest"
end
session.close

Безопасное создание новой сессии

require 'cgi'
require 'cgi/session'

cgi = CGI.new("html4")

# We make sure to delete an old session if one exists,
# not just to free resources, but to prevent the session
# from being maliciously hijacked later on.
begin
    session = CGI::Session.new(cgi, 'new_session' => false)
    session.delete
rescue ArgumentError  # if no old session
end
session = CGI::Session.new(cgi, 'new_session' => true)
session.close

Атрибуты

new_session[R]

Идентификатор этой сессии.

session_id[R]

Идентификатор этой сессии.

Методы публичного класса

new(request, option={}) Показать исходный код
# File lib/cgi/session.rb, line 289
def initialize(request, option={})
  @new_session = false
  session_key = option['session_key'] || '_session_id'
  session_id = option['session_id']
  unless session_id
    if option['new_session']
      session_id = create_new_id
      @new_session = true
    end
  end
  unless session_id
    if request.key?(session_key)
      session_id = request[session_key]
      session_id = session_id.read if session_id.respond_to?(:read)
    end
    unless session_id
      session_id, = request.cookies[session_key]
    end
    unless session_id
      unless option.fetch('new_session', true)
        raise ArgumentError, "session_key `%s' should be supplied"%session_key
      end
      session_id = create_new_id
      @new_session = true
    end
  end
  @session_id = session_id
  dbman = option['database_manager'] || FileStore
  begin
    @dbman = dbman::new(self, option)
  rescue NoSession
    unless option.fetch('new_session', true)
      raise ArgumentError, "invalid session_id `%s'"%session_id
    end
    session_id = @session_id = create_new_id unless session_id
    @new_session=true
    retry
  end
  request.instance_eval do
    @output_hidden = {session_key => session_id} unless option['no_hidden']
    @output_cookies =  [
      Cookie::new("name" => session_key,
      "value" => session_id,
      "expires" => option['session_expires'],
      "domain" => option['session_domain'],
      "secure" => option['session_secure'],
      "path" =>
      if option['session_path']
        option['session_path']
      elsif ENV["SCRIPT_NAME"]
        File::dirname(ENV["SCRIPT_NAME"])
      else
      ""
      end)
    ] unless option['no_cookies']
  end
  @dbprot = [@dbman]
  ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
end

Создать новый объект CGI::Session для request.

request — экземпляр класса CGI (см. cgi.rb). option — хеш опций для инициализации экземпляра CGI::Session. Признаются следующие опции:

session_key

имя параметра, используемого для идентификатора сессии. По умолчанию ‘_session_id’.

session_id

идентификатор сессии для использования. Если не указано, извлекается из параметра session_key запроса или генерируется автоматически для новой сессии.

new_session

если true, принудительно создать новую сессию. Если не задано, новая сессия создаётся только если текущей нет. Если false, новая сессия никогда не создаётся, и если текущей нет, а опция session_id не задана, генерируется ArgumentError.

database_manager

имя класса, предоставляющего средства хранения для сохранения состояния сессии. Встроенная поддержка предоставляется для FileStore (по умолчанию), MemoryStore, и PStore (из cgi/session/pstore.rb). Для получения более подробной информации см. документацию по этим классам.

Следующие опции также признаются, но применяются только если идентификатор сессии хранится в cookie.

session_expires

время окончания текущей сессии в виде объекта Time. Если не задано, сессия завершится при закрытии браузера пользователя.

session_domain

домен хоста, для которого эта сессия действительна. Если не задано, по умолчанию — хост сервера.

session_secure

если true, эта сессия будет работать только через HTTPS.

session_path

путь, для которого применяется эта сессия. По умолчанию — каталог скрипта CGI.

option также передаётся в инициализатор класса хранения сессий; см. документацию по каждому классу хранения сессий для поддержки опций.

Полученная или созданная сессия автоматически добавляется в request в виде cookie, а также в его таблицу output_hidden, которая используется для добавления скрытых элементов ввода в формы.

ПРЕДУПРЕЖДЕНИЕ поля output_hidden окружены тегом <fieldset> в HTML 4, что не скрыто во многих браузерах; вы можете отключить использование fieldset с помощью кода, подобного следующему (см. blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805)

cgi = CGI.new("html4")
class << cgi
    undef_method :fieldset
end

Методы публичного экземпляра

[](key) Показать исходный код
# File lib/cgi/session.rb, line 350
def [](key)
  @data ||= @dbman.restore
  @data[key]
end

Получить данные сессии для ключа key.

[]=(key, val) Показать исходный код
# File lib/cgi/session.rb, line 356
def []=(key, val)
  @write_lock ||= true
  @data ||= @dbman.restore
  @data[key] = val
end

Set данные сессии для ключа key.

close() Показать исходный код
# File lib/cgi/session.rb, line 370
def close
  @dbman.close
  @dbprot.clear
end

Сохранить данные сессии на сервере и закрыть хранилище сессий. Для некоторых типов хранилищ сессий это действие бесполезно.

delete() Показать исходный код
# File lib/cgi/session.rb, line 379
def delete
  @dbman.delete
  @dbprot.clear
end

Удалить сессию из хранилища. Также закрывает хранилище.

Обратите внимание, что данные сессии не удаляются автоматически при истечении срока действия сессии.

update() Показать исходный код
# File lib/cgi/session.rb, line 364
def update
  @dbman.update
end

Сохранить данные сессии на сервере. Для некоторых типов хранилищ сессий это действие бесполезно.

Методы закрытого экземпляра

create_new_id() Показать исходный код
# File lib/cgi/session.rb, line 171
def create_new_id
  require 'securerandom'
  begin
    # by OpenSSL, or system provided entropy pool
    session_id = SecureRandom.hex(16)
  rescue NotImplementedError
    # never happens on modern systems
    require 'digest'
    d = Digest('SHA512').new
    now = Time::now
    d.update(now.to_s)
    d.update(String(now.usec))
    d.update(String(rand(0)))
    d.update(String($$))
    d.update('foobar')
    session_id = d.hexdigest[0, 32]
  end
  session_id
end

Создать новый идентификатор сессии.

Идентификатор сессии — безопасное случайное число, сгенерированное SecureRandom, если возможно, в противном случае — SHA512 хеш, основанный на времени, случайном числе и константе. Эта процедура используется для автоматически сгенерированных идентификаторов сессий.

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API