Как настроить рельсы Authenticity Token для работы с несколькими доменами? - PullRequest
3 голосов
/ 15 апреля 2010

Я создаю приложение, которое использует субдомены в качестве дескрипторов учетных записей (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 Ответ

4 голосов
/ 16 апреля 2010

Я нашел ответ на этот вопрос здесь: http://codetunes.com/2009/04/17/dynamic-cookie-domains-with-racks-middleware/

Это решение сработало для меня, потому что мое приложение работало на Rails 2.3.5, в котором используется Rack. Запрос поступает с веб-сервера, проходит через слои промежуточного программного обеспечения и входит в приложение. Таким образом, этот уровень промежуточного программного обеспечения определяет хост, с которого осуществляется доступ к приложению, и устанавливает домен 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...