2013-02-01 17 views
11

我有一個簡單的解決方案,我已經把自己與下列對象:使用獨立的身份驗證模式on Rails的

  • 帳戶(已標記字段,即身份驗證時,返回和API調用)
  • 認證(具有AUTH_TYPE/AUTH_ID和參考賬戶)

我有一個單獨的認證模型能夠連接多種登錄方式(設備UUID,電子郵件/密碼,推特,臉書等)。但似乎在Devise的所有示例中,您都在用戶帳戶)模型上使用它。

這不是那麼不靈活?例如,OmniAuth模塊在用戶模型上存儲提供商和ID,如果您希望能夠從Twitter和Facebook登錄,會發生什麼情況,只有一個提供商有空間?

我應該使用設計上我賬戶模型或認證模式?

回答

8

最近一直在研究一個項目,我使用Devise爲不同服務保留用戶令牌。有點不同的情況下,但你的問題讓我想了一會兒。

無論如何,我會將設計綁定到帳戶模型。爲什麼?讓我們來看看。

由於我的電子郵件是能夠識別我作爲一個用戶的唯一的事情(和你提到的帳戶作爲用戶),我將它放在accounts表中對與密碼,這樣我就能開始請使用基本的電子郵件/密碼認證。我還會在authentications中保留API令牌。

正如你所提到的,OmniAuth模塊需要存儲提供者和ID。如果你想讓你的用戶能夠同時連接不同的服務(出於某種原因你需要)那麼顯然你需要保持兩個provider-id對的地方,否則每次都會被覆蓋單一用戶認證。這導致我們的身份驗證模型已經適用於此,並有帳戶的參考。

所以當尋找一個供應商 - 編號對你想檢查authentications表而不是accounts。如果找到一個,則只需返回與其關聯的account。如果沒有,那麼你檢查是否存在包含此類電子郵件的帳戶如果答案爲是,則創建新的authentication,否則創建一個,然後爲其創建authentication

更具體:

#callbacks_controller.rb 
controller Callbacks < Devise::OmniauthCallbacksContoller 
    def omniauth_callback 
    auth = request.env['omniauth.auth'] 
    authentication = Authentication.where(provider: auth.prodiver, uid: auth.uid).first 
    if authentication 
     @account = authentication.account 
    else 
     @account = Account.where(email: auth.info.email).first 
     if @account 
     @account.authentication.create(provider: auth.provider, uid: auth.uid, 
     token: auth.credentials[:token], secret: auth.credentials[:secret]) 
     else 
     @account = Account.create(email: auth.info.email, password: Devise.friendly_token[0,20]) 
     @account.authentication.create(provider: auth.provider, uid: auth.uid, 
     token: auth.credentials[:token], secret: auth.credentials[:secret]) 
     end 
    end 
    sign_in_and_redirect @account, :event => :authentication 
    end 
end 

#authentication.rb 
class Authentication < ActiveRecord::Base 
    attr_accessible :provider, :uid, :token, :secret, :account_id 
    belongs_to :account 
end 

#account.rb 
class Account < ActiveRecord::Base 
    devise :database_authenticatable 
    attr_accessible :email, :password 
    has_many :authentications 
end 

#routes.rb 
devise_for :accounts, controllers: { omniauth_callbacks: 'callbacks' } 
devise_scope :accounts do 
    get 'auth/:provider/callback' => 'callbacks#omniauth_callback' 
end 

這應該給你你需要什麼,同時保持所需的靈活性。

+0

感謝您的迴應!我只是想知道令牌;賬戶上還不應該存在該令牌嗎?我可能會使用TokenAuthenticatable策略與設計,它通常用於實際的用戶/帳戶模型?是否可以在用戶/帳戶模型上使用默認策略,但是在單獨的模型(如身份驗證)上使用TokenAuthenticatable? – thejaz

+0

不確定這是否可以使用,但始終可以覆蓋DeviseSessionsController的方法。雖然我只是親自使用'omniauthable'。 – shrimpsushi

1

您可以將所有通用邏輯分隔到模塊並僅使用相同的表格。

module UserMethods 
    #... 
end 

class User < ActiveRecord::Base 
    include UserMethods 
    devise ... 

end 

class Admin < ActiveRecord::Base 
    include UserMethods 
    self.table_name = "users" 
    devise ... 
end 

並在路由,視圖(如有必要,請參閱配置視圖)中分別配置所有設計模型。在這種情況下,您可以輕鬆處理所有不同的邏輯。

另請注意,如果您認爲設計僅適用於用戶模型,那麼您錯了。

例如, - rails g devise Admin

這將爲管理模型創建設計。

更多信息here

+0

對不起,這不回答這個問題,我不想添加另一個角色。問題是關於是否要在實際的用戶模型(或任何,我正在使用帳戶)上配置設計或在單獨的認證對象上配置設計,以使其更加靈活。 – thejaz