[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中可用的键值(及其意义)如下。
用作cookie的path. (default: File::dirname(ENV["SCRIPT_NAME"]), 直到脚本中URI的path部分的最后一条斜线为止)
用作cookie和<FORM type=hidden>的name.
(default: "_session_id")
用作会话ID. 若使用默认数据库FileStore时, 其值只能是由英文和数字构成的字符串. 若使用了该选项的话, 即使request中包含会话ID,也会被忽略. (default: 随机生成)
若其值为true,则会强行生成新的会话. 若使用了该选项的话, 即使request中包含会话ID,也会被忽略. (default: false)
数据库.
(defalut: CGI::Session::FileStore)
使用文本文件。只处理字符串数据。
使用内存中的哈希表。只在Ruby解释器的工作期间有效。
使用Marshall格式, 可以保存任何类型的数据。该功能由cgi/session/pstore.rb提供。
CGI::Session::FileStore生成会话数据时的目录名. (default: ENV["TMP"] || "/tmp")
CGI::Session::FileStore给会话数据的文件名添加的前缀. (default: "")
session['name'] = "rubikitch"
CGI::Session对象的运作方式类似于Hash, 它负责记录与索引相对应的元素值。
name = session['name']
使用其他的CGI来获取会话信息时, 要这样处理。
只要使用了CGI#out、CGI#header的话,就可以按照常规方式来处理Header输出问题了。cgi/session.rb在内部使用了cookie,而具体的处理步骤是由这些方法完成的, 所以没必要为此劳心费神。
若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
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::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>