web-dev-qa-db-fra.com

Partager une session (cookies) entre sous-domaines dans Rails?

J'ai une configuration d'application dans laquelle chaque utilisateur appartient à une société et cette société a un sous-domaine (j'utilise des sous-domaines de style Basecamp). Le problème auquel je suis confronté est que Rails crée plusieurs cookies (un pour lvh.me et un autre pour subdomain.lvh.me), ce qui provoque de nombreuses interruptions dans mon application (telles que les messages flash étant persistants bien que toutes les demandes connecté en).

J'ai ceci dans mon fichier /cofig/initilizers/session_store.rb:

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

Le domaine:: tout semble être la réponse standard que j'ai trouvée sur Google, mais cela ne semble pas fonctionner pour moi. Toute aide est appréciée! 

81
Wahaj Ali

Lorsqu'il se termine, 'domain: all' crée un cookie pour tous les différents sous-domaines visités au cours de cette session (et veille à ce qu'ils soient transmis entre les demandes). Si aucun argument de domaine n'est transmis, cela signifie qu'un nouveau cookie est créé pour chaque domaine différent visité au cours de la même session et l'ancien est ignoré. J'avais besoin d'un cookie unique persistant tout au long de la session, même lorsque le domaine change. Par conséquent, passer domain: "lvh.me" a résolu le problème du développement. Cela crée un seul cookie qui y reste entre différents sous-domaines.

Pour tous ceux qui ont besoin d’explications supplémentaires, c’est un excellent lien: http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-Rails-3/

68
Wahaj Ali

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

"La partie que vous voulez surveiller ici est que si vous définissez: domaine => : Tout est recommandé à certains endroits, cela ne fonctionnera tout simplement que si Vous utilisez localhost.: All default une taille de TLD de 1, ce qui signifie signifie que si vous testez avec Pow (myapp.dev), cela ne fonctionnera pas non plus car il s'agit d'un TLD de longueur 2. "

En d'autres termes, vous avez besoin de:

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

Aussi une bonne idée pour effacer vos cookies

58
montrealmike

Je cherchais un moyen de résoudre ce problème sans avoir à déclarer explicitement le nom de domaine. Je pouvais ainsi basculer entre localhost, lvh.me et les domaines que j'utiliserais en production sans avoir à modifier continuellement le fichier session_store.rb. Cependant, régler "domain:: all" ne semblait pas fonctionner pour moi.

En fin de compte, j’ai trouvé que j’avais besoin d’énoncer tld_length (longueur du domaine de premier niveau) dans cette expression. La longueur par défaut de tld_length est 1, tandis que exemple.lvh.me a une longueur de tld de 2 et 127.0.0.1.xip.io une longueur de tld de 5, par exemple. Donc, ce que j’avais dans le fichier session_store.rb pour les sous-domaines de Lvh.me en développement et tout ce qui se passait dans la production était le suivant.

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

J'espère que cela aide quelqu'un, car il m'a fallu beaucoup de temps pour trouver cette réponse!

20
FangedParakeet

Je suis tombé sur cette idée en cherchant le moyen le plus simple de définir le cookie comme étant le domaine racine. Il semble qu'il y ait des informations erronées sur l'option :all lorsqu'elles sont passées en tant qu'option de domaine. Pour la plupart des domaines, cela fonctionnera comme prévu en définissant le cookie sur le domaine racine (par exemple, .example.com pour test.example.com). Je pense que la plupart des gens ont rencontré des problèmes car ils utilisaient le domaine lvh.me pour tester. La regex utilisée par Rails pour trouver un domaine de premier niveau est définie comme étant DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/. Si vous notez la dernière partie, vous pouvez voir que Rails interprète lvh.me en tant que TLD similaire à com.au. Si votre cas d'utilisation a besoin de lvh.me pour fonctionner, l'option :all ne fonctionnera pas correctement. Cependant, il semble être l'option la plus simple et la meilleure pour la plupart des domaines.

TL; DR, la bonne réponse ici, en supposant que vous ne développiez pas sur un domaine de 3 lettres (ou tout domaine qui confond la regex ci-dessus) consiste à utiliser :all.

16
cassanego

Pour une raison quelconque, remplacer :all par le domaine ne fonctionnait pas (Rails 3.2.11) pour moi. Il a fallu un middleware personnalisé pour le réparer. Un résumé de cette solution est ci-dessous.

tl; dr: Vous devez écrire un middleware de rack personnalisé. Vous devez l'ajouter à votre conifg/environments/[production|development].rb. Ceci est sur Rails 3.2.11

Les sessions de cookies sont généralement stockées uniquement pour votre domaine de premier niveau.

Si vous regardez dans Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com} Vous pouvez voir qu'il y aura des entrées séparées pour sub1.yourdomain.com et othersub.yourdomain.com et yourdomain.com

Le défi consiste à utiliser le même fichier de magasin de session dans tous les sous-domaines.

Étape 1: Ajouter une classe de middleware personnalisée

C'est là que (Rack Middleware } _ entre en jeu. Quelques ressources pertinentes en matière de rack et Rails:

Voici une classe personnalisée que vous devriez ajouter dans la libCeci a été écrit par @Nader et vous devriez tous le remercier

# 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

En gros, cela permet de mapper toutes les données de votre session de cookie sur le même fichier de cookie qui est égal à votre domaine racine.

Étape 2: Ajouter à la configuration de rails

Maintenant que vous avez une classe personnalisée dans lib, assurez-vous de la charger automatiquement. Si cela ne vous disait rien, regardez ici: (chargement automatique de Rails 3 } _

La première chose à faire est de vous assurer que votre système utilise un magasin de cookies. Dans config/application.rb, nous indiquons à Rails d'utiliser un magasin de cookies.

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

La raison pour laquelle ceci est mentionné ici est à cause de la ligne :domain => :all. Il y a d'autres personnes qui ont suggéré de spécifier :domain => ".yourdomain.com" au lieu de :domain => :all. Pour une raison quelconque, cela ne fonctionnait pas pour moi et j'avais besoin de la classe Middleware personnalisée décrite ci-dessus.

Ensuite, dans votre config/environments/production.rb, ajoutez:

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

Notez que le point précédent est nécessaire. Voir " cookies de sous-domaine, envoyés dans une demande de domaine parent? } _" Pour savoir pourquoi.

Ensuite, dans votre config/environments/development.rb, ajoutez:

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

L'astuce lvh.me mappe sur localhost. C'est génial. Voir ce Railscast sur les sous-domaines } et cette note pour plus d'informations.

Espérons que cela devrait le faire. Honnêtement, je ne suis pas tout à fait sûr de savoir pourquoi le processus est si compliqué, car j'estime que les sites de sous-domaines croisés sont courants. Si quelqu'un a des idées supplémentaires sur les raisons de chacune de ces étapes, veuillez nous éclairer dans les commentaires.

16
Evan

Rails 4.x (devrait également convenir avec la version Rails 5)

Comment obtenir lvh.me:3000 et le sous-domaine dans localhost (Rails)

Simplement, j'ai partagé les cookies pour ajouter .lvh.me dans session_store.rb

Il sera partagé entre les sous-domaines sur l'hôte local admin.lvh.me:3000, lvh.me:3000 et ainsi de suite ...

#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
4
7urkm3n

As-tu essayé 

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

)

en gros, nous disons avoir un seul cookie pour le domaine de base et simplement ignorer le sous-domaine, bien que cette approche ait encore quelques défauts 

3
Naveed

soutenir Rails5

si vous voulez cela fonctionne avec n'importe quel domaine:

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

Pour configurer par environnement, vous pouvez utiliser les éléments suivants:

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

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

0
cgg5207