首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

CGI::Session

Parent:Object

Overview

该文件提供CGI :: Session类,它为CGI脚本提供会话支持。会话是一系列HTTP请求和响应链接在一起并与单个客户端相关联。与会话相关的信息在请求之间存储在服务器上。会话ID在客户端和服务器之间传递,每个请求和响应对用户都是透明的。这将状态信息添加到否则无状态的HTTP请求/响应协议。

生命周期

CGI :: Session实例是从CGI对象创建的。默认情况下,如果当前不存在该CGI :: Session实例,将启动一个新会话,如果存在,则继续此客户端的当前会话。该new_session选项可用于始终或永远不会创建新会话。有关更多详细信息,请参阅new()。

delete()从会话存储中删除一个会话。但它不会从客户端中删除会话标识。如果客户端使用相同的ID发出另一个请求,则效果将是使用旧会话的ID开始新会话。

设置和检索会话数据。

Session类将数据与会话关联为键值对。可以通过使用'[]'索引Session实例来设置和检索这些数据,这与散列(尽管不支持其他散列方法)非常相似。

当一个请求的会话处理已经完成时,会话应该使用close()方法关闭。这会将会话的状态存储到持久存储中。如果您想要将会话的状态存储到持久性存储,而不完成此请求的会话处理,请调用update()方法。

存储会话状态

调用者可以使用database_manager:: new选项指定会话数据使用的存储形式。以下存储类作为标准库的一部分提供:

CGI::Session::FileStore

将数据作为纯文本存储在平面文件中。仅适用于String数据。这是默认的存储类型。

CGI::Session::MemoryStore

将数据存储在内存散列中。只要当前的Ruby解释器实例有效,数据就会一直存在。

CGI::Session::PStore

以Marshalled格式存储数据。由cgi / session / pstore.rb提供。支持任何类型的数据,并提供文件锁定和事务支持。

自定义存储类型也可以通过使用以下方法定义类来创建:

代码语言:javascript
复制
new(session, options)
restore  # returns hash of session data.
update
close
delete

更改中会话的存储类型不起作用。特别要注意的是,默认情况下,FileStore和PStore会话数据文件具有相同的名称。如果您的应用程序从一个切换到另一个,而没有确定文件名会不同并且客户端仍然有旧的会话存在于Cookie中,那么事情就会突然崩溃!

维护会话ID。

大多数会话状态在服务器上维护。但是,会话ID必须在客户端和服务器之间反向传递以维护对此会话状态的引用。

最简单的方法是通过cookie。如果客户端启用了Cookie,则CGI :: Session类将为透过Cookie的会话ID通信提供透明支持。

如果客户端禁用了Cookie,则会话ID必须包含为客户端发送到服务器的所有请求的参数。与CGI类一起使用的CGI :: Session类将透明地将会话标识添加为使用CGI#form()HTML生成方法生成的所有表单的隐藏输入字段。没有为其他机制提供内置支持,例如URL重写。调用者负责从#session_id属性中提取会话ID并手动将其编码到URL中,并将其添加为由其他机制创建的HTML表单的隐藏输入。此外,会话过期不会自动处理。

使用示例

Setting the user's name

代码语言:javascript
复制
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

安全地创建新的会话

代码语言:javascript
复制
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_sessionR

此会话的ID。

session_idR

此会话的ID。

公共类方法

new(request, option={}) Show source

Create a new CGI::Session object for request.

requestCGI该类的一个实例(请参阅cgi.rb)。option是用于初始化此CGI :: Session实例的选项的哈希。以下选项被认可:

session_key

用于会话ID的参数名称。默认为'_session_id'。

#session_id

要使用的会话标识。如果未提供,则从session_key请求的参数中检索它,或为新会话自动生成。

#new_session

如果属实,则强制创建新会话。如果没有设置,只有当前不存在的情况下才会创建一个新的会话。如果为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字段被HTML 4代中的<fieldset>标记包围,这在许多浏览器中都是可见的; 您可能希望禁用使用类似于以下代码的字段集(请参阅blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805

代码语言:javascript
复制
cgi = CGI.new("html4")
class << cgi
    undef_method :fieldset
end
代码语言:javascript
复制
# File lib/cgi/session.rb, line 247
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

公共实例方法

显示来源

检索密钥的会话数据key

代码语言:javascript
复制
# File lib/cgi/session.rb, line 308
def [](key)
  @data ||= @dbman.restore
  @data[key]
end

[]=(key, val) 显示源

设置密钥的会话数据key

代码语言:javascript
复制
# File lib/cgi/session.rb, line 314
def []=(key, val)
  @write_lock ||= true
  @data ||= @dbman.restore
  @data[key] = val
end

close() 显示源

将会话数据存储在服务器上并关闭会话存储。对于某些会话存储类型,这是无操作。

代码语言:javascript
复制
# File lib/cgi/session.rb, line 328
def close
  @dbman.close
  @dbprot.clear
end

delete() 显示源

从存储中删除会话。也关闭存储。

请注意,会话过期后会话的数据不会自动删除。

代码语言:javascript
复制
# File lib/cgi/session.rb, line 337
def delete
  @dbman.delete
  @dbprot.clear
end

update() 显示源

将会话数据存储在服务器上。对于某些会话存储类型,这是无操作。

代码语言:javascript
复制
# File lib/cgi/session.rb, line 322
def update
  @dbman.update
end

私有实例方法

create_new_id() 显示源

创建一个新的会话ID。

如果可能的话,会话ID是SecureRandom的安全随机数,否则是基于时间,随机数和常量字符串的SHA512哈希。此例程在内部用于自动生成的会话ID。

代码语言:javascript
复制
# File lib/cgi/session.rb, line 170
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

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com