簡體   English   中英

機架:單個機架應用程序的多個會話cookie

[英]Rack: Multiple session cookies for a single rack application

如何在單個機架應用程序中與多個會話cookie(針對不同的路徑或域)進行交互?

例如,考慮使用3個位置的以下應用程序:

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

應該可以與3個會話cookie進行交互:

  • 域= www.my-app.net; 路徑= /;
  • 域= www.my-app.net; 路徑= / APP_A;
  • 域= app_b.my-app.net /; 路徑= /;

Rack :: Session :: Cookie似乎是一個不錯的選擇,但作為中間件,會話cookie必須在config.ru中設置,並且似乎僅限於每個機架應用程序一個會話cookie。

在這種特殊情況下,主機架應用程序點是輕松添加子應用程序,因此將應用程序划分到多個機架應用程序中以使用Rack :: Session :: Cookie不是一個可行的解決方案。

理想的方法是從機架應用程序代碼中自由地與多個會話cookie進行交互。

現在,我正在考慮:

  • 編寫允許與多個會話cookie交互的中間件
  • 使用CGI :: Cookie在應用程序內部實現自定義會話cookie管理

但兩者都很乏味,所以我想知道是否有更簡單的方法來實現這個功能。

提前感謝任何建議或建議。

如果有人以相同的需求運行,我發現創建一個類來管理應用程序內的會話是最簡單的方法。

Rack :: Utils有兩個不錯的快捷方式, Rack :: Utils.set_cookie_header! Utils.delete_cookie_header! 在處理cookie時,這可以使事情變得更容易。

我在使用我的應用程序的數據庫中保存會話,但支持另一個后端應該是微不足道的。

作為旁注,我提到了一些注意事項:

  • 為了確保cookie的名稱有效,我為此目的使用了子應用程序名稱的sha-1。
  • SecureRandom.urlsafe_base64對於生成會話密鑰非常有用。
  • 必須手動實施會話清理和刷新。

示例代碼

管理cookie的類,提交功能集和刪除cookie到機架。

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

管理會話的類(使用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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM