session-Rails 3 session_store域实际上是做什么的?

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

我了解您可以将session_store的域设置为在子域之间共享会话,如下所示::domain => :all

在Rails 3中,设置:domain => :all的作用是什么? 它无法让您跨顶级域共享会话,而Cookie则无法做到。 该文档说它假设一个顶级域。 那么,如果多个域访问您的应用程序会怎样?

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

什么是正确的session_store域设置,这样我可以:a)在我的主域的所有域中共享会话,例如“ mydomain.com”b)通过CNAME自定义网址(如“ some.otherdomain.com”)访问其个人子域(例如“ user1.mydomain.com”)的用户仍可以创建单独的会话。

谢谢

Nader asked 2019-11-07T21:11:08Z
5个解决方案
33 votes

好的,完成此操作的方法是在会话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
Nader answered 2019-11-07T21:11:19Z
19 votes

我认为现有的答案都无法直接回答标题中的问题,因此我想参与其中。

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

actionpack/lib/action_dispatch/middleware/cookies.rb告诉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

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

Tyler Collier answered 2019-11-07T21:12:09Z
12 votes

tl; dr:使用@Nader的代码。 但是我发现我需要将其添加到我的config/environments/development.rb中,并将我的点前缀域作为参数传递。 这是在Rails 3.2.11上

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

如果您查看config/environments/development.rb,可以看到:domain => ".yourdomain.com":domain => :allyourdomain.com会有单独的条目

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

步骤1:使用@Nader的config/environments/development.rb代码

这是机架中间件出现的地方。一些更相关的机架和导轨资源:

  • 关于机架的Railscasts
  • 机架导轨
  • 用于会话和cookie会话的机架文档

基本上,这样做是将所有cookie会话数据映射回与您的根域完全相同的cookie文件。

第2步:添加到Rails配置

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

首先是要确保您使用cookie存储在系统范围内。 在config/environments/development.rb中,我们告诉Rails使用cookie存储。

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

这里提到的原因是因为config/environments/development.rb这条线。 有人建议使用:domain => ".yourdomain.com"代替:domain => :all。出于某些原因,这对我不起作用,因此我需要如上所述的自定义中间件类。

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

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

请注意,前面的点是必需的。 请参阅“在父域请求中发送的子域cookie?” 为什么。

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

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

lvh.me技巧映射到本地主机。 这很棒。 有关更多信息,请参见此Railscast有关子域的信息和本说明。

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

Evan answered 2019-11-07T21:14:26Z
10 votes

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

Rishav Rastogi answered 2019-11-07T21:14:52Z
1 votes

嗯,

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

对我而言,:domain =>:all将会话cookie的域设置为xyz.com。 因此,不是顶级域名,而是顶级域名(TLD)之上的1级域名。

简·威廉

Jan Willem Luiten answered 2019-11-07T21:15:35Z
translate from https://stackoverflow.com:/questions/4060333/what-does-rails-3-session-store-domain-all-really-do