CGI::Session

[2001/08/26] by rubikitch

概要

管理CGI会话的库。所谓会话是指通过若干HTTP request来完成一系列动作的过程。进行会话管理时, 既可以使用cgi.rb提供的cookie, 也可以使用这个简单易懂的cgi/session.rb。会话信息采用的是类似Hash的接口。

使用该cgi/session.rb时, 由服务器来管理会话信息, 再用cookie把与会话信息相对应的会话ID传给客户端。由于cookie中并未指定expires, 所以一旦关闭浏览器, cookie也将消亡。

用法

生成

cgi = CGI::new
session = CGI::Session::new( cgi [, aHash] )

CGI对象传递给CGI::Session::new。可选参数aHash中可用的键值(及其意义)如下。

"session_path"

用作cookie的path. (default: File::dirname(ENV["SCRIPT_NAME"]), 直到脚本中URI的path部分的最后一条斜线为止)

"session_key"

用作cookie和<FORM type=hidden>的name. (default: "_session_id")

"session_id"

用作会话ID. 若使用默认数据库FileStore时, 其值只能是由英文和数字构成的字符串. 若使用了该选项的话, 即使request中包含会话ID,也会被忽略. (default: 随机生成)

"new_session"

若其值为true,则会强行生成新的会话. 若使用了该选项的话, 即使request中包含会话ID,也会被忽略. (default: false)

"database_manager"

数据库. (defalut: CGI::Session::FileStore)

CGI::Session::FileStore

使用文本文件。只处理字符串数据。

CGI::Session::MemoryStore

使用内存中的哈希表。只在Ruby解释器的工作期间有效。

CGI::Session::PStore

使用Marshall格式, 可以保存任何类型的数据。该功能由cgi/session/pstore.rb提供。

"tmpdir"

CGI::Session::FileStore生成会话数据时的目录名. (default: ENV["TMP"] || "/tmp")

"prefix"

CGI::Session::FileStore给会话数据的文件名添加的前缀. (default: "")

记录会话信息

session['name'] = "rubikitch"

CGI::Session对象的运作方式类似于Hash, 它负责记录与索引相对应的元素值。

获取会话信息。

name = session['name']

使用其他的CGI来获取会话信息时, 要这样处理。

Header输出

只要使用了CGI#out、CGI#header的话,就可以按照常规方式来处理Header输出问题了。cgi/session.rb在内部使用了cookie,而具体的处理步骤是由这些方法完成的, 所以没必要为此劳心费神。

umask值

若umask值为0022的话, 则会话信息文件的permission变为644, 因此任何用户都可以查看会话信息文件。若不想这样的话, 请在生成CGI::Session对象之前预先设置好umask值即可。

用例

该CGI例程非常简单, 输入用户名就会出现问候语。

演示例程库在这里

源代码

#!/usr/bin/ruby
require 'kconv'
require 'cgi'
require 'cgi/session'

class SessionDemo
  def initialize
    @cgi = CGI::new
    File.umask(0066)                                # 不想让别人查看会话文件
    @session = CGI::Session::new( @cgi )            # 这样生成会话。
    @cmd = "#{@cgi['cmd'].first}"                   # 这样的话,在ruby 1.8 中也可以运行了(会出现warning)
    @cmd = 'start' if @cmd.empty?
    @header = { "type" => "text/html", "charset" => "euc-jp" }

    __send__("cmd_#{@cmd}")
  end

  def cmd_start
    @cgi.out( @header ) {
      <<-END
      <html><head><title>CGI::Session Demo</title></head>
      <body>
       <form action="#{ENV['SCRIPT_NAME']}" method="get">
       <p>
       您的名字是?
       <input type="text" name="name">
       <input type="hidden" name="cmd" value="hello">
       <input type="submit" value="确定">
       </p>
       </form>
      </body></html>
      END
    }
  end

  def cmd_hello
    name = Kconv::toeuc( @cgi['name'].first )
    @session['name'] = name                         # 存入会话
    @cgi.out( @header ) {                           # 会话信息存在隐藏cookie中,所以使用CGI#out来输出
      <<-END
      <html><head><title>CGI::Session Demo</title></head>
      <body>
       <p>#{name},你好</p>
       <p><a href="#{ENV['SCRIPT_NAME']}?cmd=bye">[下一步]</a></p>
      </body></html>
      END
    }
  end

  def cmd_bye
    name = @session['name']                         # 从会话数据中获取信息
    @cgi.out( @header ) {
      <<-END
      <html><head><title>CGI::Session Demo</title></head>
      <body>
       <p>#{name}, 再见</p>
       <p><a href="#{ENV['SCRIPT_NAME']}">[返回]</a></p>
      </body></html>
      END
    }
  end
end

SessionDemo.new

class CGI::Session

类方法

CGI::Session.new(cgi[, aHash])

新生成并返回一个会话对象。

实例方法

CGI::Session#[key]

返回指定索引的值。

CGI::Session#[key] = val

设定指定索引的值。

CGI::Session#update

调用数据库类的update方法, 将会话信息存入服务器。

若是MemoryStore的话, 则不会进行任何操作。

CGI::Session#close

调用数据库类的close方法, 将会话信息存入服务器, 关闭会话存储器。

CGI::Session#delete

调用数据库类的delete方法, 从存储器中删除会话。

若是FileStore的话,就删除会话文件。若非显式地删除会话文件的话, 它将被保留下来。

CGI::HtmlExtension#form 的输出

CGI::Session.new后的CGI::HtmlExtension#form将自动输出存有会话ID的隐藏field。CGI::Session.new会自动将新生成的form field值识别为会话ID。

若使用CGI::HtmlExtension#form,并通过<INPUT TYPE="submit">来实现页面跳转的话, 就可以在那些无法使用cookie的环境中保持会话信息了。

#!/usr/bin/ruby
require 'cgi'
require 'cgi/session'

cgi = CGI::new('html3')
File.umask(0066)
session = CGI::Session::new(cgi)
cgi.out('charset'=>'euc-jp') {
  html = cgi.html {
    cgi.head { cgi.title {'form Demo'} }
    cgi.body {
      cgi.form('action'=>"#{cgi.script_name}") {
        cgi.p {
          '您的名字是?' +
          cgi.text_field('name') +
          cgi.hidden('cmd', 'hello') +
          cgi.submit('确认')
        }
      }
    }
  }
  CGI.pretty(html)
}
#=>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
  <BODY>
    <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded" action="/sample.rb">
      <P>
        您的名字是?
        <INPUT NAME="name" SIZE="40" TYPE="text">
        <INPUT NAME="cmd" TYPE="hidden" VALUE="hello">
        <INPUT TYPE="submit" VALUE="确认">
      </P>
      <INPUT TYPE="HIDDEN" NAME="_session_id" VALUE="bc315cc069266e21">    # 就是这里
    </FORM>
  </BODY>
</HTML>

参考URL