2011-09-21 13 views
8

Przenoszę projekt z Rails 3 do 3.1. Mój system uwierzytelniania został łatwo przełączony na nowe has_secure_hasword w ActiveRecord. Jedynym problemem, z którym się borykam jest to, że używam OmniAuth i mam system skonfigurowany, więc jeśli użytkownik zarejestruje się za pomocą jednego z dostawców OmniAuth, konto nie powinno wymagać hasła. Nie mogę przesłonić konfiguracji sprawdzania poprawności password_digest has_secure_password. Czy mimo to wyłączyć te sprawdzenia i napisać własne, czy też będę musiał używać moich starych ręcznie pisanych funkcji bcrypt z mojej wersji witryny Rails 3?Otrzymywanie has_secure_ps Railsów do pracy z OmniAuth

Odpowiedz

5

Skończyło się na używaniu niestandardowych metod. Jednak później zdałem sobie sprawę, że powinienem był móc użyć wywołania zwrotnego before_validation, aby sprawdzić warunki, a następnie, jeśli pasują, ustaw password_digest na coś prostego jak "0". W ten sposób podsumowanie nigdy nie będzie puste, ale jednocześnie nie powinno nigdy być sprawdzane jako poprawne hasło, co powoduje, że logują się za pośrednictwem OmniAuth.

Możesz mnie poprawić, jeśli się mylę.

+0

Mam zamiar spróbować twojej metody, daj mi znać, jeśli znajdziesz lepszy sposób. –

+3

To wydaje się łatwiejsze. Właśnie ustawiłem 'user.password_digest = SecureRandom.urlsafe_base64' w mojej metodzie' from_omniauth'. (Mimo, że po ponownym przeczytaniu odpowiedzi, domyślam się, że nie musi być randomizowana, ponieważ nie jest używana do uwierzytelniania?). Biorąc pod uwagę, że jest to o wiele szybsze - zastanawiam się, jakie jest uzasadnienie wyboru zaakceptowanej odpowiedzi? – umezo

+0

Masz rację. Poszedłem dalej i zmieniłem odpowiedź. Chociaż nadal zdecydowałem się na bezpośrednie używanie BCrypt i pisanie własnych metod hashowania hasłem. To zbyt łatwe do zrobienia i sprawia, że ​​twoje intencje są bardziej przejrzyste. –

4

Scott, twój pomysł jest poprawny. Zmagałem się z tym problemem bezskutecznie. Próbowałem zastąpić "has_secure_password" i po prostu nie zadziała. Nie ważne gdzie utknąłem kod.

Zamiast mam następujące:

class User < ActiveRecord::Base 
    has_secure_password 

    validates_presence_of :password, :on => :create, :if => :password_required 

    # Associations 
    has_many :authentications 

    # Callbacks 
    before_validation :no_password_omniauth 

    # Gets set to true if the caller is trying to authenticate with omniauth. 
    @called_omniauth = false 

    # Build new omniauth users 
    def apply_omniauth(omniauth) 
    authentications.build(
    :provider => omniauth['provider'], 
    :uid => omniauth['uid']) 
    self.first_name = omniauth['user_info']['first_name'] if self.first_name.blank? 
    self.last_name = omniauth['user_info']['last_name'] if self.last_name.blank? 
    self.email = omniauth['user_info']['email'] if omniauth['user_info']['email'] && self.email.blank? 
    @called_omniauth = true 
    end 

    def password_required 
    return false if @called_omniauth == true 
    (authentications.empty? || !password.blank?) 
    end 

    private 

    def no_password_omniauth 
    self.password_digest = 0 unless password_required 
    end 

end 

Sposób apply_omniauth jest wywoływana z kontrolera, gdy ktoś próbuje uwierzytelnić lub zarejestrować się.

Dzięki za pomysł, który przytrzasnąłeś.

+0

Zmieniłem odpowiedź na twoją, ponieważ podałeś przykład kodu. Dzięki. Zakładam więc, że nie pozwoliłoby ci zalogować się na to konto przy użyciu jakiegokolwiek hasła? –

+0

Co dokładnie używasz '@ named_omniauth'? Czy po prostu nie użyłoby 'authentications.empty? || ! password.blank? 'w twojej metodzie' password_required' wystarczy? –

+0

named_omniauth to jedyny sposób, w jaki aplikacja wie, że użytkownik loguje się przez omniauth (metoda apply_omniauth). – chourobin

Powiązane problemy