在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.com
和othersub.yourdomain.com
和yourdomain.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