代码之家  ›  专栏  ›  技术社区  ›  Nader

Rails 3会话存储域:都是做什么的?

  •  55
  • Nader  · 技术社区  · 14 年前

    更新问题以使其更清楚

    Rails.application.config.session_store :cookie_store, :key => '_my_key', :domain => "mydomain.com"

    在Rails 3中,设置是什么 :domain => :all 是吗?它不能让你在顶级域之间共享会话,cookies不能这样做。文档中说它假设有一个顶级域。那么,如果多个域访问你的应用会发生什么?

    什么是正确的会话存储域设置,以便我可以: a) 在主域的所有域中共享会话,例如“my domain.com”

    谢谢

    5 回复  |  直到 14 年前
        1
  •  33
  •   Nader    14 年前

    好的,实现这一点的方法是动态地在会话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
    
        2
  •  20
  •   Tyler Collier    10 年前

    当客户端(浏览器)转到网站时,网站会告诉客户端设置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
    

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

        3
  •  12
  •   Community CDub    8 年前

    tl;博士: 使用 @Nader 的代码。但我发现我需要把它加到我的 conifg/environments/[production|development].rb

    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

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

    第一步:使用 @良信 CustomDomainCookie

    这里就是 Rack Middleware 进来。一些更相关的rack&rails资源:

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

    步骤2:添加到Rails配置

    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" 而不是 :域=>:全部

    然后在你的 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技巧映射到本地主机。太棒了。见 this Railscast about subdomains this note 更多信息。

    希望能做到。我真的不完全清楚为什么这个过程如此复杂,因为我觉得跨域站点很常见。如果有人对每一个步骤背后的原因有任何进一步的见解,请在评论中启发我们。

        4
  •  10
  •   Rishav Rastogi    14 年前

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

        5
  •  1
  •   Jan Willem Luiten    14 年前

    六羟甲基三聚氰胺六甲醚,

    我部署了一个托管在www.xyz.com和xyz.com下的应用程序。

    巴比伦或耶路撒冷