我正在构建一个使用子域作为帐户句柄的应用程序(myaccount.domain.com),我将我的会话配置为跨子域工作,如下所示:
config.action_controller.session = {:domain => '.domain.com'}
除子域外,用户还可以在创建帐户时输入真实域名。我的Nginx配置设置为监听* .com * .net等,这是为了服务于页面。
当网站访问者在用户输入的自定义域上提交评论表单时,问题就出现了。该代码抛出了“Invalid AuthenticityToken”异常。我99%肯定这是因为用户所在的域未被指定为config.action_controller.session中的域。因此,真实性令牌没有得到匹配,因为Rails无法找到他们的会话。
所以,问题是:你能将config.action_controller.session设置为多个域,如果可以,你可以在运行时添加/删除该值而不重启应用程序吗?
答案 0 :(得分:4)
我在这里找到了这个问题的答案:http://codetunes.com/2009/04/17/dynamic-cookie-domains-with-racks-middleware/
这个解决方案对我有用,因为我的应用程序运行在使用Rack的Rails 2.3.5上。请求来自Web服务器,通过中间件层并进入应用程序。因此,此中间件层会检测访问该应用程序的主机,并为该请求设置cookie域。这是:
# app/middlewares/set_cookie_domain.rb
class SetCookieDomain
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)
domain = @default_domain.sub(/^\./, '')
host !~ Regexp.new("#{domain}$", Regexp::IGNORECASE)
end
end
# turn it on in environment.rb
config.load_paths += %W( #{RAILS_ROOT}/app/middlewares )
# production.rb
config.middleware.use "SetCookieDomain", ".example.org"
.example.org是将使用的默认域,除非通过自定义域(如site.com)访问应用程序,我们根据环境(生产/登台/开发等)为其提供不同的值。
# tests/integration/set_cookie_domain_test.rb (using Shoulda and Webrat)
require 'test_helper'
class SetCookieDomainTest < ActionController::IntegrationTest
context "when accessing site at example.org" do
setup do
host! 'example.org'
visit '/'
end
should "set cookie_domain to .example.org" do
assert_equal '.example.org', @integration_session.controller.request.session_options[:domain]
end
end
context "when accessing site at site.com" do
setup do
host! 'site.com'
visit '/'
end
should "set cookie_domain to .site.com" do
assert_equal '.site.com', @integration_session.controller.request.session_options[:domain]
end
end
context "when accessing site at site.example.org" do
setup do
host! 'site.example.org'
visit '/'
end
should "set cookie_domain to .example.org" do
assert_equal '.example.org', @integration_session.controller.request.session_options[:domain]
end
end
end