Rack: multiple session cookies for a single rack application

How can I interact with multiple session cookies (for different paths or domains) in a single rack application?

For example, given the following application using 3 locations:

  • www.my-app.net => main application
  • www.my-app.net/app_a => helper application A
  • app_b.my_app.net/=> helper application B

Must be able to interact with 3 cookie sessions:

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

Rack :: Session :: Cookie seemed to be a good choice, but as a middleware, the session cookie should be set in config.ru and apparently limited to one session cookie for each rack application.

In this special case, the main point of the rack application is the simple addition of auxiliary applications, so dividing the application in multiple racks into using Rack :: Session :: Cookie is not a viable solution.

An ideal would be a way to freely interact with multiple session cookies from the rack application code.

I am currently considering:

  • writing middleware to interact with multiple session files
  • use CGI :: Cookie to implement user control of the session cookie inside the application.

But both are pretty tedious, so I was wondering if there is an easier way to achieve this functionality.

Thanks in advance for any advice or suggestions.

+4
source share
1 answer

If someone works with the same needs, I found that making a class for managing sessions inside an application was the easiest way.

Rack :: Utils has 2 bright shortcuts, Rack :: Utils.set_cookie_header! and Utils.delete_cookie_header! , which can simplify the work with cookies.

I save sessions in the database used by my application, but this should be trivial to support a different back-end.

As an additional note, a few considerations I came up with:

  • To be sure that the cookie name is valid, I use sha-1 of the sub-application name for this purpose.
  • SecureRandom.urlsafe_base64 is useful for generating a session key.
  • Session cleanup and updating must be done manually.

Code example

A class that manages cookies, an installed commit function, and deletes cookies in a 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 management class (using Mongo as a backend):

 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 

Each time @framework.response.cookies.set is called, it pushes the cookie data into the Framework::Response::Cookies class @cookies .

Before submitting a response, calling Framework::Response::Cookies.commit terminates cookies using Rack::Utils .

+3
source

Source: https://habr.com/ru/post/1443576/


All Articles