是否有Rack中间件用于使用没有cookie的会话?

tro*_*skn 10 ruby cookies session rack

随Rack提供的会话管理中间件都基于用于识别用户的cookie.由于我正在开发api,我宁愿将session-id显式地作为查询字符串参数传递.看一下代码库,似乎并没有考虑这个用例,因为所有的会话中间件都是从一个读写/写入cookie的公共类扩展而来的.

所以我的问题是 - 是否有一个项目维护一个替代的Rack中间件或一个用于机架内置中间件的猴子补丁,这将允许我在查询字符串而不是cookie存储上维护session-id?

joe*_*son 8

Rack可以使用自定义会话ID项而不是cookie:

require 'rack/session/abstract/id'
Run Code Online (Sandbox Code Playgroud)

Rack文档可能是一个有用的开始搜索的地方.我相信你正在寻找"跳过"选项(或"推迟"选项).

文档:

ID设置了实现基于id的会话服务的基本框架.发送给客户端以维护会话的Cookie仅包含id引用.只需要覆盖#get_session和#set_session.

所有参数都是可选的.

  • :key确定cookie的名称,默认为'rack.session'
  • :path,:domain,:expire_after,:secure,和:httponly设置相关的cookie选项,如Rack :: Response#add_cookie
  • :skip不会在响应中设置cookie也不会更新会话状态
  • :defer不会在响应中设置cookie,但如果与后端一起使用,仍会更新会话状态
  • :renew(依赖于实现)将提示生成新的会话ID,并迁移要在新id处引用的数据.如果:设置了延迟,它将被覆盖并且将设置cookie.
  • :sidbits设置生成的会话ID的长度位数.

这些选项可以基于每个请求设置,位于env ['rack.session.options']的位置.此外,会话的id可以在key:id的options散列中找到.强烈建议不要更改其值.

是Rack :: Utils :: Context兼容.

默认不包括在内; 你必须要求'rack/session/abstract/id'才能使用.

资源:

  class ID
    DEFAULT_OPTIONS = {
      :key =>           'rack.session',
      :path =>          '/',
      :domain =>        nil,
      :expire_after =>  nil,
      :secure =>        false,
      :httponly =>      true,
      :defer =>         false,
      :renew =>         false,
      :sidbits =>       128,
      :cookie_only =>   true,
      :secure_random => (::SecureRandom rescue false)
    }
Run Code Online (Sandbox Code Playgroud)

我希望这能带给你一个领导......当你了解更多信息时,你能在这里分享你的成果吗?

编辑:

神奇的诀窍是将选项:cookie_only => false:defer => true.当然,标准的Rack :: Session :: Cookie在这里没有多大意义,所以你可以这样做:

use Rack::Session::Pool, :cookie_only => false, :defer => true
Run Code Online (Sandbox Code Playgroud)

有趣的是,您可以在运行时更改选项.在我的用例中,我实际上需要支持传统的基于cookie的机制以及显式参数传递样式,所以我做了以下事情:

class WebApp < Sinatra::Base

  configure do
    use Rack::Session::Pool, :key => 'session_id'
  end

  before do
    # Switch to parameter based session management if the client is an ios device
    if env['HTTP_USER_AGENT'] =~ /iOS/
      session.options[:cookie_only] = false
      session.options[:defer] = true
    end
  end

  get '/' do
    session[:user_id] ||= nil # This triggers a session-write, giving us a valid session-id
    body "session_id=#{session.id}"
  end
end
Run Code Online (Sandbox Code Playgroud)