2013-02-01 12 views
11

Mam proste rozwiązanie Zrobiłem sobie z następujących obiektów:Zastosowanie modelu z osobna uwierzytelniania opracować on Rails

  • konto (ma pole tokena, który jest zwracany podczas uwierzytelniania i stosowane w API)
  • Authentication (ma AUTH_TYPE/auth_id i odniesienie do rachunku)

mam oddzielny Authentication model, aby móc połączyć kilka sposobów logowania (UUID urządzenia, adres e-mail/hasło, twitter, facebook itp.). Wygląda jednak na to, że we wszystkich przykładach Devise używa się go na modelu(Account).

Czy to nie jest mniej elastyczne? Na przykład moduł OmniAuth przechowuje dostawcę i identyfikator w modelu User, co się stanie, jeśli chcesz zalogować się zarówno z Twittera, jak i Facebooka, jest tylko miejsce dla jednego dostawcy?

Czy powinienem używać Devise na moim modelu Konto lub modelu Authentication?

Odpowiedz

8

Pracowałem ostatnio nad projektem, w którym korzystałem z Devise, aby zachować tokeny użytkownika dla różnych usług. Nieco inny przypadek, ale wciąż twoje pytanie mnie zastanowiło.

Wezwę Devise do Konto model mimo to. Czemu? Zobaczmy.

Ponieważ mój e-mail jest jedyną rzeczą, która może identyfikować się jako użytkownik (i odnoszą się do konta jak Użytkownika) Chciałbym umieścić go w accounts stole w parze z hasłem tak, że jestem w stanie początkowo korzystać z podstawowego uwierzytelniania za pomocą poczty e-mail/hasła. Również będę przechowywać tokeny API w authentications.

Jak już wspomniano, moduł OmniAuth musi przechowywać dostawcę i identyfikator. Jeśli chcesz, aby Twój użytkownik mógł łączyć się z różnymi usługami w tym samym czasie, (i z jakiegoś powodu), to oczywiście musisz zachować obie pary identyfikatorów dostawcy, w przeciwnym razie po prostu zostanie nadpisany za każdym razem, gdy pojedynczy użytkownik uwierzytelnia się.To prowadzi nas do modelu Authentication, który jest już odpowiedni do tego i ma odniesienie do Konta.

Szukając pary usługodawców, należy sprawdzić tabelę authentications, a nie accounts. Jeśli zostanie znaleziony, po prostu zwrócisz skojarzony z nim account. Jeśli nie, sprawdź, czy istnieje konto zawierające taki e-mail. Utwórz nową authentication, jeśli odpowiedź brzmi "tak", w przeciwnym razie utwórz ją, a następnie utwórz dla niej authentication.

Aby być bardziej konkretne:

#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 

To powinno dać ci to, czego potrzebujesz, zachowując elastyczność chcesz.

+0

Dzięki za odpowiedź! Zastanawiam się tylko nad tokenem; czy token nie powinien znajdować się również na koncie? Prawdopodobnie wykorzystam strategię TokenAuthenticatable z narzędziem i jest ona zwykle używana w rzeczywistym modelu użytkownika/konta? Czy możliwe jest użycie domyślnych strategii w modelu użytkownika/konta, ale TokenAuthenticatable w oddzielnym modelu, takim jak uwierzytelnianie? – thejaz

+0

Nie jestem pewien, czy to możliwe, ale możesz zawsze zastąpić metody z DeviseSessionsController. Po prostu osobiście używałbym 'omniautowalnego'. – shrimpsushi

1

Możesz oddzielić całą wspólną logikę od modułu i użyć tylko tej samej tabeli.

module UserMethods 
    #... 
end 

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

end 

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

Skonfiguruj wszystkie modele devise niezależnie w trasach, widokach (jeśli to konieczne, zobacz Konfigurowanie widoków). W takim przypadku możesz łatwo przetworzyć całą logikę.

Należy również pamiętać, że jeśli sądzisz, że program jest przeznaczony wyłącznie dla modelu użytkownika, oznacza to, że się mylisz.

Na przykład. - rails g devise Admin

Spowoduje to utworzenie narzędzia dla modelu administratora.

Więcej informacji here.

+0

Niestety, to nie odpowiada na pytanie, nie chcę dodawać kolejnej roli. Pytanie brzmi, czy skonfigurować devise na faktycznym modelu użytkownika (lub cokolwiek, używam konta) lub na oddzielnym obiekcie uwierzytelniania, aby uczynić go bardziej elastycznym. – thejaz

Powiązane problemy