gpt4 book ai didi

ruby - Rack:单个 Rack 应用程序的多个 session cookie

转载 作者:数据小太阳 更新时间:2023-10-29 07:34:28 27 4
gpt4 key购买 nike

如何在单个 Rack 应用程序中与多个 session cookie(针对不同的路径或域)进行交互?

例如,考虑以下使用 3 个位置的应用程序:

  • www.my-app.net => 主应用
  • www.my-app.net/app_a => 子应用 A
  • app_b.my_app.net/=> 子应用 B

应该能够与 3 个 session cookie 交互:

  • domain=www.my-app.net;路径=/;
  • domain=www.my-app.net;路径=/app_a;
  • domain=app_b.my-app.net/;路径=/;

Rack::Session::Cookie 似乎是一个不错的选择,但作为中间件, session cookie 必须在 config.ru 中设置,而且似乎每个 Rack 应用程序只能使用一个 session cookie。

在这种特殊情况下,主要的 Rack 应用点是方便添加子应用程序,因此将应用程序划分在多个 Rack 应用程序中使用 Rack::Session::Cookie 不是一个可行的解决方案。

理想的是一种从 Rack 应用程序代码内部与多个 session cookie 自由交互的方法。

目前,我正在考虑:

  • 编写允许与多个 session cookie 交互的中间件
  • 使用 CGI::Cookie 在应用程序内部实现自定义 session cookie 管理

但两者都非常乏味,所以我想知道是否有更简单的方法来实现此功能。

提前感谢您的任何意见或建议。

最佳答案

如果有人有相同的需求,我发现创建一个类来管理应用程序内部的 session 是最简单的方法。

Rack::Utils 有 2 个不错的快捷方式,Rack::Utils.set_cookie_header!Utils.delete_cookie_header!这确实可以使处理 cookie 时的事情变得更容易。

我将 session 保存在我的应用程序使用的数据库中,但支持另一个后端应该是微不足道的。

作为旁注,我提出了一些注意事项:

  • 为了确保 cookie 的名称有效,我为此使用了子应用程序名称的 sha-1。
  • SecureRandom.urlsafe_base64对于生成 session key 很有用。
  • session 清理和刷新必须手动实现。

示例代码

管理cookies的类,commit函数设置和删除cookies到rack。

class Framework::Response::Cookies

def set( params )
@cookies[params.delete( :name )] = params
end

def remove( params )
@remove_cookies[params.delete( :name )] = params
end

def commit( headers )
@cookies.each_pair do |name, params|
Rack::Utils.set_cookie_header!( headers, name, params )
end
@remove_cookies.each_pair do |name, params|
Rack::Utils.delete_cookie_header!( headers, name, params )
end
end

end

管理 session 的类(使用 Mongo 作为后端):

class Database::Mongo::Session < Session

def save
expire = Time.now + @session_ttl
@framework.content.db.find_and_modify( self.collection_name, {
:query => { :name => @session_name, :id => @session_id },
:update => { :expire => expire, :name => @session_name, :id => @new_session_id || @session_id , :variables => @variables.to_hash },
:upsert => true
})
@framework.response.cookies.set(
:name => @session_name,
:value => @new_session_id || @session_id,
:path => @framework.applications.active.active_request['path'],
:domain => @framework.applications.active.active_request['host'],
:httponly => true
)
end

def delete
@framework.content.db.remove( self.collection_name, { :id => @session_id } )
@framework.response.cookies.remove( :name => @session_name )
end

end

每次调用@framework.response.cookies.set时,都会推送一个cookie数据给Framework::Response::Cookies@cookies 变量。

在提供响应之前,调用 Framework::Response::Cookies.commit 使用 Rack::Utils 提交 cookie。

关于ruby - Rack:单个 Rack 应用程序的多个 session cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13188899/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com