Rails 3 session_store域名是什么:一切都真的如此?

Nad*_*der 57 cookies subdomain session ruby-on-rails

更新了问题,使其更加清晰

我知道你可以设置session_store的域来共享子域之间的会话,如下所示: Rails.application.config.session_store :cookie_store, :key => '_my_key', :domain => "mydomain.com"

在Rails 3中,设置有:domain => :all什么作用?它不能让您在顶级域名之间共享会话,Cookie无法做到这一点.文档说它假设一个顶级域名.那么如果多个域访问您的应用会发生什么?

在我的应用中,我的用户可以创建一个主域的个人子域,但也可以通过他们自己的自定义域访问该子域.

什么是正确的session_store域设置,这样我可以:a)在我的主域名,如"mydomain.com" B)谁访问他们的个人子域名,例如"user1.mydomain.com"用户的所有域共享会话通过CNAME定制像"some.otherdomain.com"这样的网址仍然可以创建单独的会话.

谢谢

Nad*_*der 33

好的,完成此任务的方法是动态地在会话cookie上设置域.要尽早做到这一点,它应该作为机架中间件完成:

# 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
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你,我有完全相同的情况,这有帮助!如果其他人(像我一样)第一次添加Rack Middleware,可以使用Railscast:http://railscasts.com/episodes/151-rack-middleware.如果添加到Rails 3应用程序,请参阅以下链接的加载路径:http://stackoverflow.com/questions/11478920/rails-3-how-to-declare-rack-middleware-in-application-rb (5认同)

Tyl*_*ier 19

我认为任何现有的答案都没有直接回答标题中的问题所以我想填写.

当客户端(浏览器)访问网站时,网站会告诉客户端设置cookie.当它这样做时,它指定cookie名称,值,域和路径.

:domain => :all 告诉Rails在cookie域(这是浏览器浏览过的任何主机)前放置一个点,这样cookie就适用于所有子域.

以下是Rails 4.1(actionpack/lib/action_dispatch/middleware/cookies.rb)中的相关代码:

  def handle_options(options) #:nodoc:
    options[:path] ||= "/"

    if options[:domain] == :all
      # if there is a provided tld length then we use it otherwise default domain regexp
      domain_regexp = options[:tld_length] ? /([^.]+\.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP

      # if host is not ip and matches domain regexp
      # (ip confirms to domain regexp so we explicitly check for ip)
      options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ domain_regexp)
        ".#{$&}"
      end
    elsif options[:domain].is_a? Array
      # if host matches one of the supplied domains without a dot in front of it
      options[:domain] = options[:domain].find {|domain| @host.include? domain.sub(/^\./, '') }
    end
  end
Run Code Online (Sandbox Code Playgroud)

我看到你已经回答了关于允许子域有单独会话的问题的第二部分.


Eva*_*van 12

tl; dr:使用@Nader的代码.但我发现我需要将它添加到我的conifg/environments/[production|development].rb并通过我的dot-prefixed-domain作为参数.这是在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步:使用@NaderCustomDomainCookie代码

这就是Rack Middleware的用武之地.一些更相关的机架和轨道资源:

基本上它的作用是将所有cookie会话数据映射回与您的根域相同的完全相同的cookie文件.

第2步:添加到Rails配置

既然您在lib中有自定义类,请确保自动加载它.如果这对您没有任何意义,请看这里:Rails 3自动加载

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

# We use a cookie_store for session data
config.session_store :cookie_store,
                     :key => '_yourappsession',
                     :domain => :all
Run Code Online (Sandbox Code Playgroud)

这里提到的原因是因为这:domain => :all条线.还有其他人建议指定:domain => ".yourdomain.com"而不是:domain => :all.出于某种原因,这对我不起作用,我需要如上所述的自定义中间件类.

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

config.middleware.use "CustomDomainCookie", ".yourdomain.com"
Run Code Online (Sandbox Code Playgroud)

请注意,前面的点是必要的.有关原因,请参阅" 在父域请求中发送的子域cookie? ".

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

config.middleware.use "CustomDomainCookie", ".lvh.me"
Run Code Online (Sandbox Code Playgroud)

lvh.me技巧映射到localhost.这很棒.有关详细信息,请参阅此有关子域的Railscast此注释.

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


Ris*_*ogi 10

此选项用于确保应用程序能够跨子域共享会话.:all选项假定我们的应用程序的顶级域大小为1.如果不是,那么我们可以指定域名,并将其用作会话的基本域.