如何设置rails Authenticity Token以使用多个域?

时间:2010-04-15 12:10:08

标签: ruby-on-rails ruby

我正在构建一个使用子域作为帐户句柄的应用程序(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设置为多个域,如果可以,你可以在运行时添加/删除该值而不重启应用程序吗?

1 个答案:

答案 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