在Internet Explorer中不能使用子域的3个会话

时间:2011-07-26 04:33:25

标签: ruby-on-rails-3 devise session-cookies subdomain

我正在使用子域名的rails 3应用程序。我使用了railscast#221“rails 3 in rails 3”(http://railscasts.com/episodes/221-subdomains-in-rails-3)作为指南,一切顺利,除了资源管理器。

为了让我的会话跨越所有子域,我将下一行放在session_store.rb中,如教程所述:

MyApp.application.config.session_store :cookie_store, :key => '_myapp_session', :domain => "example.com"

我已经在Firefox和Chrome上测试了我的应用程序并且运行良好,但由于某种原因,在Internet Explorer中根本无法正常工作。这种行为很奇怪,因为有时似乎会话在我的所有子域中共享,但有些其他子域名我登录,其他sudomains我没有登录。

我找不到任何理由,我很感激任何想法...

我正在使用Devise进行rails 3.0.5身份验证

2 个答案:

答案 0 :(得分:6)

我相信您需要将domain值更改为.example.com(前导点表示可以跨子域使用Cookie):

MyApp.application.config.session_store :cookie_store, :key => '_myapp_session', :domain => ".example.com"

答案 1 :(得分:4)

由于某种原因,对于在子域上设置的任何会话数据,这都不起作用(rails 3.2.11)。它花了一块自定义中间件来修复它。该解决方案的摘要如下。

tl; dr:您需要编写自定义的Rack Middleware。您需要将其添加到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.com以及yourdomain.com

会有单独的条目

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

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

这就是Rack Middleware的用武之地。一些相关的机架& rails资源:

以下是您应在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:添加到Rails配置

既然您在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行。还有其他人建议指定:domain => ".yourdomain.com"而不是:domain => :all。出于某种原因,这对我不起作用,我需要如上所述的自定义中间件类。

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

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

请注意前面的点是必要的。有关原因,请参阅“sub-domain cookies, sent in a parent domain request?”。

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

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

lvh.me技巧映射到localhost。这很棒。有关详细信息,请参阅this Railscast about subdomainsthis note

希望应该这样做。老实说,我不完全确定为什么这个过程很复杂,因为我觉得跨域子站点很常见。如果有人对这些步骤背后的原因有任何进一步的见解,请在评论中启发我们。