¿Compartir sesión (cookies) entre subdominios en Rails?

Tengo una configuración de aplicación en la que cada usuario pertenece a una empresa, y esa empresa tiene un subdominio (estoy usando subdominios de estilo basecamp). El problema al que me enfrento es que rails está creando varias cookies (una para lvh.me y otra para subdomain.lvh.me), lo que está causando bastantes cortes en mi aplicación (como los mensajes flash que son persistentes a pesar de todas las solicitudes) registrado).

Tengo esto en mi archivo /cofig/initilizers/session_store.rb:

AppName::Application.config.session_store :cookie_store, key: '_application_devise_session', domain: :all 

El dominio:: todo parece ser la respuesta estándar que encontré en Google, pero eso no parece funcionar para mí. ¡Cualquier ayuda es apreciada!

A medida que sale, ‘dominio: todos’ crea una cookie para todos los diferentes subdominios que se visitan durante esa sesión (y asegura que se pasen entre una solicitud y otra). Si no se pasa un argumento de dominio, significa que se crea una nueva cookie para cada dominio diferente que se visita en la misma sesión y se descarta el anterior. Lo que necesitaba era una única cookie que sea persistente durante toda la sesión, incluso cuando el dominio cambia. Por lo tanto, pasar el domain: lvh.me resolvió el problema en el desarrollo. Esto crea una única cookie que se queda allí entre diferentes subdominios.

Para cualquiera que necesite más explicaciones, este es un excelente enlace: http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/

http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/

“La parte que desea tener en cuenta aquí es que si establece: domain =>: todo lo que se recomienda en algunos lugares, simplemente no funcionará a menos que esté usando localhost.: Todos los valores predeterminados a una longitud de TLD de 1 , lo que significa que si estás probando con Pow (myapp.dev) tampoco funcionará porque es un TLD de longitud 2 “.

En otras palabras, necesitas:

  App.config.session_store ... , :domain => :all, :tld_length => 2 

También es una buena idea limpiar tus cookies

Estaba buscando una manera de resolver este problema sin tener que indicar explícitamente el nombre de dominio, así que podría saltar entre localhost, lvh.me y los dominios que usaría en producción sin tener que seguir editando el archivo session_store.rb. Sin embargo, configurar “dominio:: todos” no parecía funcionar para mí.

Finalmente descubrí que necesitaba indicar la tld_length (longitud del dominio de nivel superior) en esa expresión. El tld_length predeterminado es 1 mientras que example.lvh.me tiene un tld_length de 2 y 127.0.0.1.xip.io tiene un tld_length de 5, por ejemplo. Entonces, lo que tenía en el archivo session_store.rb para subdominios en lvh.me en desarrollo y cualquier otra cosa en producción era la siguiente.

 MyApp::Application.config.session_store :cookie_store, key: '_MyApp_session', domain: :all, tld_length: 2 

Espero que esto ayude a alguien, ya que me llevó mucho tiempo encontrar esta respuesta.

Por alguna razón reemplazar :all con el dominio no funcionó (Rails 3.2.11) para mí. Tomó un pedazo de Middleware personalizado para arreglarlo. Un resumen de esa solución está a continuación.

tl; dr: Necesita escribir un Rack Middleware personalizado. conifg/environments/[production|development].rb agregarlo a su conifg/environments/[production|development].rb . Esto está en Rails 3.2.11

Las sesiones de cookies generalmente se almacenan solo para su dominio de nivel superior.

Si miras en Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com} Puedes ver que habrá entradas separadas para sub1.yourdomain.com y othersub.yourdomain.com y othersub.yourdomain.com

El desafío es usar el mismo archivo de tienda de sesión en todos los subdominios.

Paso 1: agregar una clase personalizada de middleware

Aquí es donde aparece Rack Middleware . Algunos recursos relevantes de rack y Rails:

  • Railscasts sobre Rack
  • Railsguide para Rack
  • Documentación en bastidor para sesssions de forma abstracta y para sesiones de cookies

Aquí hay una clase personalizada que debes agregar en la lib Esto fue escrito por @Nader y todos deberían agradecerle

 # Custom Domain Cookie # # Set the cookie domain to the custom domain if it's present class CustomDomainCookie def initialize(app, default_domain) @app = app @default_domain = default_domain end def call(env) host = env["HTTP_HOST"].split(':').first env["rack.session.options"][:domain] = custom_domain?(host) ? ".#{host}" : "#{@default_domain}" @app.call(env) end def custom_domain?(host) host !~ /#{@default_domain.sub(/^\./, '')}/i end end 

Básicamente, lo que hace es mapear todos los datos de la sesión de cookies en el mismo archivo de cookies que es igual a su dominio raíz.

Paso 2: Agregar a Rails Config

Ahora que tienes una clase personalizada en lib, asegúrate de que esté autocargada. Si eso no significaba nada para ti, mira aquí: Rails 3 autoload

Lo primero es asegurarse de estar en todo el sistema utilizando una tienda de cookies. En config/application.rb le decimos a Rails que use una tienda de cookies.

 # We use a cookie_store for session data config.session_store :cookie_store, :key => '_yourappsession', :domain => :all 

La razón por la que esto se menciona aquí se debe a :domain => :all line. Hay otras personas que han sugerido especificar :domain => ".yourdomain.com" lugar de :domain => :all . Por alguna razón, esto no funcionó para mí y necesitaba la clase de Middleware personalizada como se describe arriba.

Luego, en su config/environments/production.rb agregue:

 config.middleware.use "CustomDomainCookie", ".yourdomain.com" 

Tenga en cuenta que el punto anterior es necesario. Consulte ” cookies del subdominio, enviadas en una solicitud de dominio principal ” por qué.

Luego, en su config/environments/development.rb agregue:

 config.middleware.use "CustomDomainCookie", ".lvh.me" 

El truco lvh.me se asigna a localhost. Es impresionante. Vea este Railscast sobre los subdominios y esta nota para más información.

Con suerte eso debería hacerlo. Honestamente, no estoy del todo seguro de por qué el proceso es así de intrincado, ya que creo que los sitios de subdominios cruzados son comunes. Si alguien tiene más información sobre las razones detrás de cada uno de estos pasos, por favor, infórmenos en los comentarios.

Me encontré con esto mientras buscaba la forma más sencilla de configurar la cookie para que sea el dominio raíz. Parece que hay alguna información errónea sobre la opción :all cuando se pasa como la opción de dominio. Para la mayoría de los dominios, en realidad funcionará como se espera, estableciendo la cookie en el dominio raíz (por ejemplo, .example.com para test.example.com ). Creo que la mayoría de las personas experimentaron problemas ya que están usando el dominio lvh.me para probar. La expresión regular utilizada por los Rails para encontrar un dominio de nivel superior se define como DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/ . Si nota la última parte, puede ver que los Rails interpretan lvh.me como un TLD similar a com.au Si su caso de uso necesita lvh.me para funcionar, entonces la opción :all no funcionará correctamente, sin embargo, parece ser la opción más simple y mejor para la mayoría de los dominios.

TL; DR, la respuesta correcta aquí, suponiendo que no está desarrollando en un dominio de 3 letras (o cualquier dominio que confunde la expresión regular anterior) es usar :all .

Has probado

 AppName::Application.config.session_store :cookie_store, key: '_application_devise_session', domain: 'lvh.me' 

)

básicamente, estamos diciendo que tienen una sola cookie para el dominio base y simplemente ignoran el subdominio … aunque este enfoque todavía tiene algunos defectos …

Rails 4.x (también debería estar bien con la versión de Rails 5)

Cómo obtener lvh.me:3000 y el subdominio en localhost (Rails)

Simplemente, he compartido cookies para agregar .lvh.me a session_store.rb ,

Se compartirá entre subdominios en localhost admin.lvh.me:3000 , lvh.me:3000 y así sucesivamente …

 #config/initializers/session_store.rb if Rails.env.production? Rails.application.config.session_store :cookie_store, key: '_app_name_session', domain: ".domain_name.com" else Rails.application.config.session_store :cookie_store, key: '_app_name_session', domain: '.lvh.me' end