2013-12-11 87 views
16

我在Rails 3應用中使用Devise進行身份驗證。該應用程序使用PostgreSQL模式和Apartment gem來促進多租戶。在用Rails和Devise註冊後將用戶登錄到他們的子域

登錄和退出特定的子域正在很好地工作帳戶被創建。用戶只能在他們的特定帳戶的子域名上登錄,這很好。

這裏就是我遇到的問題...

一個全新的用戶點擊註冊網址爲:

http://foo.com/signup

默認情況下,當他們點擊提交,新帳戶被創建,但用戶發送到:

http://foo.com/dashboard

相反,我想他們去:

http://myaccount.foo.com/dashboard

爲了實現這一點,我在registrations_controller.rb文件推翻了after_sign_up_path_for方法:

def after_sign_up_path_for(resource) 
    root_url(:subdomain => resource.account.subdomain) 
end 

這按預期工作 - 它加載正確的URL - 但用戶的會議是創建爲根域(foo.com)而不是子域,所以用戶被要求登錄。

我發現的一個建議是將config/initializers/session_store.rb更改爲:

config.session_store :cookie_store, :key => '_domain_session', :domain => :all 

但是,這允許任何人登錄到任何子域的帳戶,顯然不是很酷。

問:我怎樣才能確保在註冊創建的會話有效期爲這是在註冊過程中創建

+0

您需要更改cookie,就像您在問題中寫的一樣。否則用戶將始終在子域上未知。一個簡單的解決方案是編寫一個before-filter或者擴展現有的登錄邏輯來檢查正確的子域。這是通常完成的事情,因爲您不想依靠Cookie進行身份驗證。 – phoet

+0

@phoet嗯,我想過這個。所以我應該做':domain =>'.mydomain'(允許跨子域Cookie),然後修改我的'before_filter'來檢查正確的子域? –

+0

我使用了一箇中間件的cookie的東西:https://github.com/phoet/on_ruby/blob/master/app/middlewares/cookie_domain.rb – phoet

回答

21

你可以在你的config.session_store使用domain: :all選項和子域只是有一個before_action正如評論中的一些人所建議的那樣。

所以,你仍然會在配置/初始化/ session_store.rb或在配置/ application.rb中的代碼:

config.session_store :cookie_store, :key => '_domain_session', :domain => :all 

然後在你的application_controller添加以下代碼:

#app/controllers/application_controller.rb 
before_action :check_subdomain 

def check_subdomain 
    unless request.subdomain == current_user.account.subdomain 
    redirect_to root_path, alert: "You are not authorized to access that subdomain." 
    end 
end 
+1

這個工作, wrinkle:如果我將會話移動到數據庫(如'session_store.rb'建議的),當我創建一個全新的帳戶(在http://example.com)時,我被重定向到http://foo.example.com我登錄了(太棒了!)。然而,我採取的下一步行動迫使我再次登錄。如果我將會話保存在cookie中,會話將根據需要保持不變。任何想法發生了什麼? –

+0

您使用的是哪個版本的Rails?在Rails 4中,activerecord-session_store已被刪除。唯一可用的選項是:cookie_store,:mem_cache_store和:disabled。如果您的會話數據超過4kb,那麼您將需要使用:mem_cache_store。否則,最好堅持使用:cookie_store。建議不要將sql db用於會話,因爲它比較慢並且是不必要的負載。這裏有一篇文章:http://blog.remarkablelabs.com/2012/12/activerecord-sessionstore-gem-extraction-rails-4-countdown-to-2013 – Gjaldon

+0

@RobSobers,讓我知道如果答案已經幫助或如果有任何你需要的澄清。 – Gjaldon

1

覆蓋設計會話控制器。

創建與確切路徑app/controllers/devise/sessions_controller.rb

覆蓋在該控制器的sessions_controller類的文件。粘貼鏈接中找到的代碼。https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb

class Devise::SessionsController < DeviseController 
# copy-paste the devise session controller below. 
... 
end 

編輯create行動,以滿足您的需求。

def create 
    self.resource = warden.authenticate!(auth_options) 
    set_flash_message(:notice, :signed_in) if is_flashing_format? 
    sign_in(resource_name, resource) 
    yield resource if block_given? 
    respond_with resource, :location => after_sign_in_path_for(resource) 
end 

我想看看我是否能找出究竟如何使這項工作,但我確實知道你想要的結果是通過重寫色器件會話控制器實現的。

編輯

如果您正在使用跨子域的cookie,你可以強制使用的before_filter子域的會話。例如

before_action do 
    redirect_to root_path, alert: 'That subdomain does not belong to you' if request.subdomain != current_user.subdomain 
end 
+0

在哪裏寫這個before_action因爲它寫在應用程序控制器將調用它每次調用anymethod時,會給錯誤 –

相關問題