Ruby-on-rails Rails 3 session_store domain :all 到底做了什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4060333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does Rails 3 session_store domain :all really do?
提问by Nader
Updated question to make it more clear
更新了问题以使其更清楚
I understand that you can set the domain of your session_store to share sessions between subdomains like this: Rails.application.config.session_store :cookie_store, :key => '_my_key', :domain => "mydomain.com"
我知道您可以将 session_store 的域设置为在子域之间共享会话,如下所示: Rails.application.config.session_store :cookie_store, :key => '_my_key', :domain => "mydomain.com"
in Rails 3, what does the setting :domain => :alldo? It can't let you share sessions across top-level domains, cookies can't do that. The documentation says it assumes one top level domain. So what happens if multiple domains access your app?
在 Rails 3 中,设置有:domain => :all什么作用?它不能让您跨顶级域共享会话,cookie 不能这样做。文档说它假设了一个顶级域。那么如果多个域访问您的应用程序会发生什么?
In my app, my users can create personal subdomains of one main domain, but then can also access that subdomain via their own custom domain.
在我的应用程序中,我的用户可以创建一个主域的个人子域,但也可以通过他们自己的自定义域访问该子域。
What is the correct session_store domain setting so that I can: a) share sessions across all domains of my primary domain, eg "mydomain.com" b) users who access their personal subdomain eg "user1.mydomain.com" via a CNAME custom url like "some.otherdomain.com" can still create separate sessions.
什么是正确的 session_store 域设置,以便我可以:a) 在我的主域的所有域之间共享会话,例如“mydomain.com” b) 通过 CNAME 自定义访问其个人子域的用户,例如“user1.mydomain.com”像“some.otherdomain.com”这样的 url 仍然可以创建单独的会话。
Thanks
谢谢
采纳答案by Nader
OK, the way to accomplish this is to set the domain on the session cookie dynamically. To do this early enough it should be done as rack middleware:
好的,实现这一点的方法是在会话 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
回答by Tyler Collier
I didn't think any of the existing answers directly answered the question in the title so I wanted to chip in.
我认为现有的任何答案都没有直接回答标题中的问题,所以我想插手。
When the client (browser) goes to a website, the website tells the client to set a cookie. When it does so, it specifies the cookie name, value, domain, and path.
当客户端(浏览器)访问某个网站时,该网站会告诉客户端设置 cookie。这样做时,它会指定 cookie 名称、值、域和路径。
:domain => :alltells Rails to put a dot in front of the cookie domain (which is whatever host your browser has browsed to), such that the cookie applies to all subdomains.
:domain => :all告诉 Rails 在 cookie 域(这是您的浏览器浏览到的任何主机)前面放一个点,这样 cookie 就适用于所有子域。
Here is the relevant code from Rails 4.1 (actionpack/lib/action_dispatch/middleware/cookies.rb):
以下是 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
I see you've already answered the second part of your question about allowing subdomains to have separate sessions.
我看到您已经回答了关于允许子域具有单独会话的问题的第二部分。
回答by Evan
tl;dr:Use @Nader's code. BUT I found I needed add it into my conifg/environments/[production|development].rband pass my dot-prefixed-domain as an argument. This is on Rails 3.2.11
tl;dr:使用@Nader的代码。但是我发现我需要将它添加到我的conifg/environments/[production|development].rb并将我的点前缀域作为参数传递。这是在 Rails 3.2.11 上
Cookie sessions are usually stored only for your top level domain.
Cookie 会话通常只为您的顶级域存储。
If you look in Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}You can see that there will be separate entries for sub1.yourdomain.comand othersub.yourdomain.comand yourdomain.com
如果您查看Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}您可以看到将有单独的条目sub1.yourdomain.com和othersub.yourdomain.com和yourdomain.com
The challenge is to use the same session store file across all subdomains.
挑战是在所有子域中使用相同的会话存储文件。
Step 1: Use @Nader's CustomDomainCookiecode
第 1 步:使用@Nader的CustomDomainCookie代码
This is where Rack Middlewarecomes in. Some more relevant rack & rails resources:
这就是机架中间件的用武之地。一些更相关的机架和导轨资源:
- Railscasts about Rack
- Railsguide for Rack
- Rack documentation for sesssions abstractlyand for cookie sessions
Basically what this does is that it will map all of your cookie session data back onto the exact same cookie file that is equal to your root domain.
基本上,它的作用是将您的所有 cookie 会话数据映射回与您的根域完全相同的 cookie 文件。
Step 2: Add To Rails Config
第 2 步:添加到 Rails 配置
Now that you have a custom class in lib, make sure are autoloading it. If that meant nothing to you, look here: Rails 3 autoload
现在您在 lib 中有一个自定义类,请确保自动加载它。如果这对您来说毫无意义,请看这里:Rails 3 autoload
The first thing is to make sure that you are system-wide using a cookie store. In config/application.rbwe tell Rails to use a cookie store.
第一件事是确保您在系统范围内使用 cookie 存储。在config/application.rb我们告诉Rails使用cookie存储。
# We use a cookie_store for session data
config.session_store :cookie_store,
:key => '_yourappsession',
:domain => :all
The reason this is here is mentioned here is because of the :domain => :allline. There are other people that have suggested to specify :domain => ".yourdomain.com"instead of :domain => :all. For some reason this did not work for me and I needed the custom Middleware class as described above.
这里提到这里的原因是因为这:domain => :all条线。还有其他人建议指定:domain => ".yourdomain.com"而不是:domain => :all. 出于某种原因,这对我不起作用,我需要如上所述的自定义中间件类。
Then in your config/environments/production.rbadd:
然后在您config/environments/production.rb添加:
config.middleware.use "CustomDomainCookie", ".yourdomain.com"
Note that the preceding dot is necessary. See "sub-domain cookies, sent in a parent domain request?" for why.
请注意,前面的点是必需的。请参阅“在父域请求中发送的子域 cookie?”了解原因。
Then in your config/environments/development.rbadd:
然后在您config/environments/development.rb添加:
config.middleware.use "CustomDomainCookie", ".lvh.me"
The lvh.me trick maps onto localhost. It's awesome. See this Railscast about subdomainsand this notefor more info.
lvh.me 技巧映射到本地主机。这很棒。有关更多信息,请参阅有关子域的 Railscast和此注释。
Hopefully that should do it. I honestly am not entirely sure why the process is this convoluted, as I feel cross subdomain sites are common. If anyone has any further insights into the reasons behind each of these steps, please enlighten us in the comments.
希望应该这样做。老实说,我不完全确定为什么这个过程如此复杂,因为我觉得跨子域站点很常见。如果有人对每个步骤背后的原因有任何进一步的了解,请在评论中启发我们。
回答by Rishav Rastogi
This option is used to make sure the application will be able to share sessions across subdomains. The :all option assumes that our application has a top-level domain size of 1. If not then we can specify a domain name instead and that will be used as the base domain for the session.
此选项用于确保应用程序能够跨子域共享会话。:all 选项假定我们的应用程序的顶级域大小为 1。如果不是,那么我们可以指定一个域名,并将其用作会话的基本域。
回答by Jan Willem Luiten
Hmmm,
嗯,
I deploy an application that is hosted under www.xyz.com and under xyz.com.
我部署了一个托管在 www.xyz.com 和 xyz.com 下的应用程序。
For me, :domain => :all sets the domain for the session-cookie to xyz.com. So not for a top-level domain but for 1 level above the tld.
对我来说,:domain => :all 将 session-cookie 的域设置为 xyz.com。所以不是针对顶级域,而是针对 tld 之上的 1 个级别。
Jan Willem
简·威廉

