2010-04-15 32 views
3

我建立一個使用子域作爲帳戶手柄的應用程序(myaccount.domain.com),我有我的會話配置跨子域工作,像這樣:如何設置rails Authenticity Token與多個域一起使用?

config.action_controller.session = {:domain => '.domain.com'} 

除了一個子域用戶在創建帳戶時可以輸入真實的域名。我的Nginx配置被設置爲監視* .com * .net等,並且正在努力提供頁面。

問題出在網站訪問者在用戶輸入的自定義域上提交評論表單時。該代碼拋出「Invalid AuthenticityToken」異常。我99%確定這是因爲用戶所在的域未在config.action_controller.session中指定爲域。因此,真實性令牌沒有得到匹配,因爲Rails找不到他們的會話。

所以,問題是:你可以將config.action_controller.session設置爲多於一個域,如果是的話,你可以在運行時添加/刪除該值,而無需重新啓動應用程序?

回答

4

我找到了這個問題的答案在這裏:http://codetunes.com/2009/04/17/dynamic-cookie-domains-with-racks-middleware/

該解決方案爲我,因爲我的應用程序是on 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 
相關問題