在Rails中的子域之间共享会话(cookie)?

我有一个应用程序设置,其中每个用户属于一个公司,该公司有一个子域(我正在使用basecamp风格子域)。 我面临的问题是,轨道是创build多个cookie(一个为lvh.me和另一个为subdomain.lvh.me),这是在我的应用程序造成了不less中断(如闪存消息是持久性的,虽然所有请求一次login)。

我在我的/cofig/initilizers/session_store.rb文件中有这个:

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

域名::​​似乎都是我在Google上find的标准答案,但这似乎不适合我。 任何帮助表示赞赏!

因为它打开了“域:所有”创build一个cookie在该会话期间访问的所有不同的子域(并确保它们之间传递请求)。 如果没有域parameter passing,这意味着为同一个会话中访问的每个不同的域创build一个新的cookie,旧的cookie被丢弃。 我需要的是在整个会话期间持续存在的单个cookie,即使域发生更改也是如此。 因此,通过domain: lvh.me解决了开发中的问题。 这将创build一个单独的cookie,并保留在不同的子域之间。

对于需要进一步解释的人来说,这是一个很好的链接: 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/

“这里你要注意的一点是,如果你设置了domain =>:在某些地方推荐一切,除非你使用本地主机,否则它将不起作用。:所有默认的TLD长度为1 ,这意味着如果您使用Pow(myapp.dev)进行testing,则无法运行,因为这是长度为2的TLD。

换句话说,你需要:

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

清除Cookie也是一个好主意

我正在寻找一种方法来解决这个问题,而不必明确说明域名,所以我可以跳转本地主机,lvh.me,我将在生产中使用的任何域,而不必保持编辑session_store.rb文件。 但是,设置“域名:全部”似乎并没有为我工作。

最终,我发现我需要在该expression式中声明tld_length(顶级域名长度)。 例如,默认的tld_length是1,而example.lvh.me的tld_length是2,而127.0.0.1.xip.io的tld_length是5。 所以,我在开发中的lvh.me上的子域的session_store.rb文件中以及生产中的其他内容如下所示。

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

希望这可以帮助别人,因为花了很长时间才find这个答案!

出于某种原因replace:all与域没有工作(轨3.2.11)对我来说。 它花了一个定制的中间件来解决它。 该解决scheme的总结如下。

tl; dr:您需要编写一个自定义的机架中间件。 您需要将其添加到您的conifg/environments/[production|development].rb 。 这是Rails 3.2.11

Cookie会话通常只存储在您的顶级域名中。

如果您查看Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}您可以看到sub1.yourdomain.comothersub.yourdomain.comyourdomain.com

挑战是在所有子域中使用相同的会话存储文件。

第1步:添加自定义中间件类

这是Rack Middleware进来的地方。一些相关的机架和导轨资源:

  • 关于Rack的Railscasts
  • Railsguide机架
  • 为抽象的框架文档抽象地和cookie会话

这是一个自定义的类,你应该添加到lib 这是由@Nader写的,你应该感谢他

 # 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 

基本上,它所做的就是将所有的Cookie会话数据映射回与根域相同的cookie文件。

第2步:添加到Railsconfiguration

现在你在lib中有一个自定义类,确保自动加载它。 如果这对你来说毫无意义,请看这里: Rails 3 autoload

首先要确保您在系统范围内使用Cookie存储。 在config/application.rb我们告诉Rails使用cookie存储。

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

这里提到的原因是因为:domain => :all行。 还有其他人build议指定:domain => ".yourdomain.com"而不是:domain => :all 。 出于某种原因,这不适合我,我需要如上所述的自定义中间件类。

然后在你的config/environments/production.rb添加:

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

请注意,前面的点是必要的。 请参阅“ 在父域请求中发送的子域cookie? ”原因。

然后在你的config/environments/development.rb添加:

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

lvh.me技巧映射到本地主机上。 这很棒。 看到这个Railscast关于子域名和这个笔记的更多信息。

希望应该这样做。 我真的不完全确定为什么这个过程是这个错综复杂的,因为我觉得跨子网站是常见的。 如果有人对这些步骤背后的原因有进一步的了解,请在评论中给我们启发。

我在find将cookie设置为根域的最简单方法的时候遇到了这个问题。 当作为域选项传递时,似乎有一些关于:all选项的错误信息。 对于大多数域,它实际上会按预期工作,将Cookie设置为根域(例如.example.com )。 我想大多数人遇到问题,因为他们正在使用域lvh.me来testing。 rails用于查找顶级域的正则expression式被定义为DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/ 。 如果您注意到最后一部分,您可以看到,rails将lvh.me解释为类似于com.au的TLD。 如果您的用例需要lvh.me才能正常工作,那么:all选项将无法正常工作,但对大多数域来说,这似乎是最简单和最好的select。

TL; DR,这里的正确答案,假设你没有开发一个3字母域(或任何混淆上述正则expression式的域)是使用:all

你试过了吗

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

基本上我们说基础域有单个cookie,只是忽略子域..虽然这种方法有一些缺陷仍然…

Rails的4.x (也应该罚款与Rails 5版本)

如何获得lvh.me:3000和子域在localhost(Rails)

简单地说,我已经共享了cookies来将.lvh.me添加到session_store.rb

它将在本地主机admin.lvh.me:3000子域之间共享…

 #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