Condividere la sessione (cookie) tra i sottodomini in Rails?


92

Ho una configurazione dell'app in cui ogni utente appartiene a un'azienda e quella società ha un sottodominio (sto usando sottodomini in stile campo base). Il problema che sto affrontando è che rails sta creando più cookie (uno per lvh.me e un altro per subdomain.lvh.me) che sta causando alcune interruzioni nella mia applicazione (come i messaggi flash persistenti anche se tutte le richieste una volta registrato in).

Ho questo nel mio file /cofig/initilizers/session_store.rb:

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

Il dominio:: tutto sembra essere la risposta standard che ho trovato su Google, ma non sembra funzionare per me. Qualsiasi aiuto è apprezzato!

Risposte:


74

Man mano che si scopre 'dominio: tutti' crea un cookie per tutti i diversi sottodomini che vengono visitati durante quella sessione (e assicura che vengano passati tra una richiesta e l'altra). Se non viene passato alcun argomento di dominio, significa che viene creato un nuovo cookie per ogni diverso dominio che viene visitato nella stessa sessione e quello vecchio viene scartato. Quello di cui avevo bisogno era un singolo cookie che fosse persistente per tutta la sessione, anche quando il dominio cambia. Quindi, il passaggio ha domain: "lvh.me"risolto il problema in fase di sviluppo. Questo crea un singolo cookie che rimane lì tra diversi sottodomini.

Per chiunque abbia bisogno di ulteriori spiegazioni, questo è un ottimo collegamento: http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/


2
Grazie Amico .. Ho affrontato questo problema in uno dei miei progetti .. Finalmente ho trovato la soluzione ..
Shirjeel Alam

3
Assicurati di utilizzare lo stesso config.secret_key_basein tutte le tue applicazioni, altrimenti non sarà in grado di decodificare il cookie.
Bruno Buccolo

5
Non vedo alcuna domanda relativa a questo per Rails 4. Sai se questo è cambiato. Non riesco a farlo funzionare con il mio progetto. Continua a ricreare i cookie. Grazie.
Andy

Cosa succede se voglio utilizzare CacheStoreper memorizzare le sessioni in memcached?
Amit Patel

2
Con Rails4, ho scoperto che funzionava solo per i sottodomini con trattini ma non con trattini Appname::Application.config.session_store :cookie_store, key: '_appname_session', domain: :all, tld_length: 2
bassi

68

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

"La parte a cui vuoi prestare attenzione qui è che se imposti: domain =>: all like è consigliato in alcuni punti, semplicemente non funzionerà a meno che tu non stia utilizzando localhost.: Tutto il valore predefinito è una lunghezza TLD di 1 , il che significa che se stai testando con Pow (myapp.dev) non funzionerà neanche perché è un TLD di lunghezza 2. "

In altre parole hai bisogno di:

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

Anche una buona idea per cancellare i cookie


1
Questa è la risposta migliore perché l'unica modifica funziona in tutti gli ambienti (app.com e app.dev). Il middleware personalizzato non è necessario. Ottimo anche per cancellare i biscotti!
Turadg

1
ti manca il, :tld_length => 2
montrealmike

1
Assicurati di utilizzare lo stesso config.secret_key_basein tutte le tue applicazioni, altrimenti non sarà in grado di decodificare il cookie.
Bruno Buccolo

4
:domain => :allnon funzionerà in Rails 4, prova domain => 'lvh.me', tld_length = 2. Ha funzionato per me
Minh Triet

1
Con Rails 4.2 ho ottenuto buoni risultati usando solo domain: :all, tld_length: 2il lvh.medominio.
zwippie

24

Stavo cercando un modo per risolvere questo problema senza dover dichiarare esplicitamente il nome del dominio, in modo da poter saltare tra localhost, lvh.me e qualsiasi dominio avrei usato in produzione senza dover continuare a modificare il file session_store.rb. Tuttavia, l'impostazione "dominio:: all" non sembrava funzionare per me.

Alla fine ho scoperto che avevo bisogno di indicare tld_length (lunghezza del dominio di primo livello) in quell'espressione. Il valore predefinito tld_length è 1 mentre example.lvh.me ha un tld_length di 2 e 127.0.0.1.xip.io ha un tld_length di 5, ad esempio. Quindi quello che avevo nel file session_store.rb per i sottodomini su lvh.me in fase di sviluppo e qualsiasi altra cosa in produzione era il seguente.

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

Spero che questo aiuti qualcuno, poiché mi ci è voluto molto tempo per trovare questa risposta!


19

Per qualche motivo la sostituzione :allcon il dominio non ha funzionato (rails 3.2.11) per me. Ci è voluto un pezzo di middleware personalizzato per risolverlo. Di seguito è riportato un riepilogo di tale soluzione.

tl; dr: è necessario scrivere un middleware per rack personalizzato. Devi aggiungerlo al tuo file conifg/environments/[production|development].rb. Questo è su Rails 3.2.11

Le sessioni cookie vengono solitamente memorizzate solo per il tuo dominio di primo livello.

Se guardi in Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}Puoi vedere che ci saranno voci separate per sub1.yourdomain.come othersub.yourdomain.comeyourdomain.com

La sfida è utilizzare lo stesso file di archivio di sessione in tutti i sottodomini.

Passaggio 1: aggiungere una classe middleware personalizzata

È qui che entra in gioco il Rack Middleware . Alcune risorse rilevanti per rack e binari:

Ecco una classe personalizzata che dovresti aggiungere in lib Questo è stato scritto da @Nader e dovresti ringraziarlo tutti

# 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

Fondamentalmente ciò che fa è che mapperà tutti i dati della sessione dei cookie sullo stesso identico file cookie che è uguale al tuo dominio principale.

Passaggio 2: Aggiungi a Rails Config

Ora che hai una classe personalizzata in lib, assicurati di caricarla automaticamente. Se che nulla significato per te, un'occhiata qui: Rails 3 autoload

La prima cosa è assicurarsi di essere a livello di sistema utilizzando un cookie store. In config/application.rbdiciamo a Rails di utilizzare un cookie store.

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

Il motivo per cui questo è qui è menzionato qui è a causa della :domain => :alllinea. Ci sono altre persone che hanno suggerito di specificare :domain => ".yourdomain.com"invece di :domain => :all. Per qualche motivo questo non ha funzionato per me e avevo bisogno della classe Middleware personalizzata come descritto sopra.

Quindi nella tua config/environments/production.rbaggiunta:

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

Notare che il punto precedente è necessario. Vedi " cookie di sottodominio, inviati in una richiesta di dominio padre? " Per il motivo.

Quindi nella tua config/environments/development.rbaggiunta:

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

Il trucco lvh.me si mappa su localhost. È meraviglioso. Vedi questo Railscast sui sottodomini e questa nota per maggiori informazioni.

Si spera che dovrebbe farlo. Onestamente non sono del tutto sicuro del motivo per cui il processo è così contorto, poiché ritengo che i siti di sottodomini incrociati siano comuni. Se qualcuno ha ulteriori informazioni sui motivi alla base di ciascuno di questi passaggi, ti preghiamo di chiarirci nei commenti.


C'è un modo per farlo funzionare con più domini di primo livello? Ho un prodotto che funziona in diversi paesi. Qui assumiamo che il dominio predefinito sia tuodominio.com, ma cosa succederebbe se dovesse funzionare per .be .sv .fr .com.br .com.ar e altri? Grazie.
Marc Lainez

Non riesco proprio a farlo funzionare. Sto sviluppando in rails 4 e sembra che i rial ignorino gentilmente tutto il codice sopra. Semplicemente non vuole condividere la sessione tra sottodomini.
Ole Henrik Skogstrøm

@ OleHenrikSkogstrøm Assicurati di usare lo stesso config.secret_key_basein tutte le tue applicazioni, altrimenti non sarà in grado di decodificare il cookie.
Bruno Buccolo

17

Mi sono imbattuto in questo mentre cercavo il modo più semplice per impostare il cookie come dominio principale. Sembra che ci sia qualche disinformazione :allsull'opzione quando viene passata come opzione di dominio. Per la maggior parte dei domini, funzionerà effettivamente come previsto, impostando il cookie sul dominio principale (ad esempio .example.comper test.example.com). Penso che la maggior parte delle persone abbia riscontrato problemi poiché utilizza il dominio lvh.meper eseguire il test. La regex utilizzata da rails per trovare un dominio di primo livello è definita DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/. Se noti l'ultima parte, puoi vedere che rails viene interpretato lvh.mecome un TLD simile a com.au. Se il tuo caso d'uso deve lvh.mefunzionare, l' :allopzione non funzionerà correttamente, tuttavia, sembra essere l'opzione più semplice e migliore per la maggior parte dei domini.

TL; DR, la risposta corretta qui, supponendo che tu non stia sviluppando su un dominio di 3 lettere (o qualsiasi dominio che confonde la regex sopra) è da usare :all.


Grazie, questo mi ha finalmente aiutato a capire perché così tante risposte consigliavano un tld_length di 2 ma perché non ne avevo bisogno!
Zuppa di cane

Questa risposta deve essere più in alto. Grazie Signore.
luca.busin

"lvh.me come TLD simile a com.au" BTW Rails dovrebbe effettivamente interpretare .me allo stesso modo in quanto è anche un dominio nazionale (Montenegro).
mahemoff

7

Rails 4.x (dovrebbe andare bene anche con le versioni di Rails 5/6)

Come ottenere lvh.me:3000 e sottodominio in localhost (Rails)

Sviluppo: ho condiviso cookie per l'aggiunta .lvh.mein session_store.rb,

Esso sarà condiviso tra i sottodomini su localhost admin.lvh.me:3000, lvh.me:3000e così via ...

#config/initializers/session_store.rb

domain = Rails.env.production? ? ".domain_name.com" : ".lvh.me"

Rails.application.config.session_store :cookie_store, 
                      key: '_app_name_session', domain: domain

4

Hai provato

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

)

fondamentalmente stiamo dicendo di avere un singolo cookie per il dominio di base e ignorare semplicemente il sottodominio ... sebbene questo approccio abbia ancora alcuni difetti ...


1

guide di supporto 5

se vuoi funziona con qualsiasi dominio:

Rails.application.config.session_store :cookie_store, key: '_my_app_session', domain: :all, tld_length: 2

Per configurare per ambiente è possibile utilizzare quanto segue:

Rails.application.config.session_store :cookie_store, key: '_my_app_session', domain: {
  production: '.example.com',
  development: '.example.dev'
}.fetch(Rails.env.to_sym, :all)

Rif: https://github.com/plataformatec/devise/wiki/How-To:-Use-subdomains


0

Se utilizzi Redis per session store.

if Rails.env.development?
    Rails.application.config.session_store :redis_store, {
       servers: [
        { host: 'localhost', port: 6379},
      ],
      key: '_app_session',
      expire_after: 1.day,
      domain: :all
    }

else
    Rails.application.config.session_store :redis_store, {
       servers: [
        { host: HOST_URL, port: PORT},
      ],
      key: '_app_session',
      expire_after: 1.day,
      domain: '.domain.com',
      tld_length: 2
    }
    
end 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.