Ruby CGI Cookie

在 Ruby 的 CGI(Common Gateway Interface) 编程中,Cookie 是一种用于在客户端(浏览器)和服务器之间存储和传递小型数据的机制,常用于会话管理、用户身份验证或保存用户偏好。Ruby 的 cgi 库提供了 CGI::Cookie 类来创建、设置和读取 Cookies。以下是对 Ruby CGI 中 Cookie 使用的中文讲解,涵盖核心方法、创建与读取 Cookies、示例代码及注意事项,力求简洁清晰,并避免重复之前的内容(如 CGI 编程概述)。


1. Cookie 简介

Cookies 是存储在浏览器中的键值对,由服务器通过 HTTP 响应发送,浏览器在后续请求中自动回传。Ruby 的 CGI 模块通过 CGI::Cookie 类管理 Cookies,支持设置属性(如过期时间、路径)并解析客户端发送的 Cookies。

用途

  • 保存用户会话信息(如用户 ID)。
  • 跟踪用户行为或偏好。
  • 实现简单的状态管理。

2. CGI::Cookie 类

CGI::Cookie 用于创建和操作 Cookie 对象,常用属性包括:

  • name:Cookie 的名称(必需)。
  • value:Cookie 的值(字符串或字符串数组)。
  • expires:过期时间(Time 对象)。
  • path:Cookie 有效的路径(如 / 表示整个站点)。
  • domain:Cookie 有效的域名。
  • secure:布尔值,仅 HTTPS 连接可用(默认 false)。
  • httponly:布尔值,禁止 JavaScript 访问 Cookie(默认 false)。

创建 Cookie

require 'cgi'

cookie = CGI::Cookie.new(
  'name' => 'user_id',
  'value' => '12345',
  'expires' => Time.now + 3600,  # 1 小时后过期
  'path' => '/',
  'secure' => true,
  'httponly' => true
)

3. 设置 Cookie

Cookies 通过 CGI#outCGI#header 方法在 HTTP 响应头中设置。

使用 cgi.out

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

cgi = CGI.new
cookie = CGI::Cookie.new('name' => 'user_id', 'value' => '12345', 'expires' => Time.now + 3600)
cgi.out('cookie' => [cookie]) do
  "<html><body><p>Cookie set for user_id: 12345</p></body></html>"
end

说明

  • cookie 选项接受单个 CGI::Cookie 或 Cookie 数组。
  • 浏览器接收后存储 Cookie,后续请求会自动携带。

使用 cgi.header

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

cgi = CGI.new
cookie = CGI::Cookie.new('name' => 'session', 'value' => 'abc123')
puts cgi.header('cookie' => [cookie])
puts "<html><body><p>Cookie set!</p></body></html>"

4. 读取 Cookie

客户端发送的 Cookies 存储在 cgi.cookies 中,返回一个哈希,键为 Cookie 名称,值为 CGI::Cookie 对象数组。

示例

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

cgi = CGI.new
user_id = cgi.cookies['user_id'][0]&.value || 'Guest'
cgi.out do
  "<html><body><p>Welcome, User ID: #{CGI.escapeHTML(user_id)}</p></body></html>"
end

说明

  • cgi.cookies['user_id'] 返回 Cookie 数组,[0].value 获取第一个值。
  • 使用 CGI.escapeHTML 转义,防止 XSS 攻击。
  • &.value 避免空 Cookie 导致的错误。

5. 更新与删除 Cookie

  • 更新 Cookie:设置相同名称的新 Cookie,覆盖旧值。
  cookie = CGI::Cookie.new('name' => 'user_id', 'value' => '67890')
  cgi.out('cookie' => [cookie]) { "<p>Cookie updated!</p>" }
  • 删除 Cookie:设置过期时间为过去。
  cookie = CGI::Cookie.new('name' => 'user_id', 'value' => '', 'expires' => Time.now - 3600)
  cgi.out('cookie' => [cookie]) { "<p>Cookie deleted!</p>" }

6. 综合示例

以下示例实现一个简单的 CGI 脚本,通过 Cookie 记录用户最后访问的用户名,并显示欢迎消息。

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

cgi = CGI.new
name = cgi['name'] || 'Guest'
cookie = CGI::Cookie.new(
  'name' => 'last_user',
  'value' => name,
  'expires' => Time.now + 86400,  # 1 天
  'path' => '/'
)

begin
  last_user = cgi.cookies['last_user'][0]&.value || 'None'
  cgi.out('cookie' => [cookie]) do
    cgi.html do
      cgi.body do
        cgi.h1 { "Welcome, #{CGI.escapeHTML(name)}!" } +
        cgi.form('action' => '/cgi-bin/cookie.rb', 'method' => 'post') do
          cgi.p { "Name: " + cgi.text_field('name') } +
          cgi.submit('Submit')
        end +
        cgi.p { "Last user: #{CGI.escapeHTML(last_user)}" }
      end
    end
  end
rescue => e
  cgi.out('status' => '400') { "<html><body><p>Error: #{CGI.escapeHTML(e.message)}</p></body></html>" }
end

保存:保存为 /usr/lib/cgi-bin/cookie.rb,设置权限(chmod +x)。
访问http://localhost/cgi-bin/cookie.rb?name=Alice
功能

  • 显示欢迎消息和输入表单。
  • 通过 Cookie 保存上一个用户名。
  • 使用 CGI.escapeHTML 防止 XSS。

7. 注意事项

  • 安全性
  • 使用 secure: true 确保 Cookie 仅在 HTTPS 传输。
  • 使用 httponly: true 防止 JavaScript 访问 Cookie。
  • 转义 Cookie 值(CGI.escapeHTML)防止 XSS。
  • 不要存储敏感信息(如密码)在 Cookie 中。
  • 过期时间
  • 未设置 expires 的 Cookie 为会话 Cookie,浏览器关闭后失效。
  • 设置合理的 expiresmax-age 控制 Cookie 寿命。
  • 路径与域名
  • path: '/' 使 Cookie 在整个站点有效。
  • domain 设置需匹配服务器域名,否则 Cookie 无效。
  • 大小限制:浏览器通常限制 Cookie 大小(约 4KB),避免存储过多数据。
  • 调试:检查浏览器开发者工具或服务器日志(如 /var/log/apache2/access.log)。
  • 现代替代:Rails/Sinatra 使用更高级的会话管理(如 session),性能和安全性更优。

8. 总结

Ruby 的 CGI::Cookie 类通过 name, value, expires 等属性管理 Cookies,结合 cgi.outcgi.header 设置 Cookie,使用 cgi.cookies 读取客户端 Cookie。Cookies 适合存储小型数据(如用户 ID),但需注意安全性(secure, httponly, 转义)和大小限制。CGI 编程简单直接,但现代 Web 开发推荐使用 Rails 等框架替代。

如果你需要更复杂的 Cookie 操作(如多值 Cookie、加密)或有其他问题,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注