2013-09-06 13 views
34

Używam klejnotu devise, po kliknięciu w link potwierdzający chcę się bezpośrednio zalogować. Obecnie prosi o ponowne zalogowanie.Unikaj logowania po kliknieciu linku potwierdzajacego za pomoca programu Devise Gem?

Ostatnio dodałem następujące w devise zainicjować plik:

config.allow_insecure_token_lookup = true 
config.secret_key = 'a8d814803c0bcc735ce657adc77793459d00154cdd7532c13d3489600dc4e963f86e14beb593a32cbe9dbbe9197c9ce50a30102f363d90350052dc8d69930033' 

jakieś sugestie?

+0

Czy Twój link potwierdzający zawierał 'token dostępu '? –

+1

tak, przykładowy link: http: // localhost: 3000/users/confirmation? Confirm_token = ede7fbc3203644c0ff40cf31844389d460607a7d5f13ce95bcddd25c8fce667 –

Odpowiedz

54

W poprzednich wersjach Devise użytkownik został automatycznie zalogowany po potwierdzeniu. Oznaczało to, że każdy, kto miałby dostęp do e-maila z potwierdzeniem, mógł zalogować się na czyjeś konto, po prostu klikając link.

Automatyczne podpisywanie użytkownika może również być szkodliwe w przepływie pracy potwierdzającym e-mail. Wyobraź sobie, że użytkownik decyduje się na zmianę swojego adresu e-mail, a jednocześnie robi literówkę na nowym adresie e-mail. Wiadomość e-mail zostanie wysłana na inny adres, który za pomocą tokena będzie mógł zalogować się na to konto.

Jeśli użytkownik natychmiast poprawi wiadomość e-mail, nie wyrządzi szkody. Ale jeśli nie, ktoś inny mógłby zalogować się na to konto, a użytkownik nie wiedziałby, że to się stało.

Z tego powodu Devise 3.1 nie powoduje już automatycznego podpisania użytkownika po potwierdzeniu. Można tymczasowo przynieść starego zachowania powrotem po uaktualnieniu przez ustawienie następujących w config/inicjalizatorów/devise.rb:

config.allow_insecure_sign_in_after_confirmation = true

Ta opcja będzie dostępna tylko tymczasowo w celu ułatwienia migracji.

+1

Działa poprawnie. Dziękuję bardzo, Rajarshi Das! Świetna pomoc. –

+1

Szaleję, szukając źródła danych i nie mogłem znaleźć miejsca, w którym użytkownik loguje się po potwierdzeniu. I nie jest, dziękuję za wyjaśnienie! – Mirko

+1

Jeśli możesz uzyskać dostęp do konta e-mail użytkownika, możesz mimo to zresetować jego hasło, więc nie jestem pewien Rozumiem tutaj problem bezpieczeństwa. To samo dotyczy drugiego przykładu, jeśli otrzymasz wiadomość e-mail z potwierdzeniem zmiany adresu e-mail, możesz zmienić hasło po tym samym numerze. – Jean

51

Flaga config.allow_insecure_sign_in_after_confirmation nie jest już obsługiwana w programie Devise.

Należy mieć na uwadze możliwe obawy dotyczące bezpieczeństwa polegające na automatycznym rejestrowaniu użytkowników podczas potwierdzania ich konta (http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/), jednak w przypadku niektórych aplikacji korzyść pod względem komfortu użytkowania może być warta kompromisu w zakresie bezpieczeństwa.

W końcu ryzyko związane z bezpieczeństwem polega na tym, że a) użytkownik nieprawidłowo wpisuje swoją wiadomość e-mail, b) nie natychmiast poprawia swój błąd, c) wpisany adres e-mail odpowiada poprawnemu i działającemu adresowi e-mail, d) osoba, która nieprawidłowo otrzyma wiadomość e-mail, otworzy ją i kliknie link.

Jeśli jest to akceptowalny profil ryzyka dla danej aplikacji, można zastąpić ConfirmationsController opracować:

class ConfirmationsController < Devise::ConfirmationsController 
    def show 
    self.resource = resource_class.confirm_by_token(params[:confirmation_token]) 
    yield resource if block_given? 

    if resource.errors.empty? 
     set_flash_message(:notice, :confirmed) if is_flashing_format? 
     sign_in(resource) # <= THIS LINE ADDED 
     respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) } 
    else 
     respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new } 
    end 
    end 
end 

i droga do niego w swoim routes.rb:

devise_for :users, controllers: { confirmations: 'confirmations' } 
+0

Dlaczego nie można zrobić coś, aby zidentyfikować, że komputer, na którym znajduje się łącze, jest tą samą maszyną, która spowodowała wysłanie tego e-maila? Na przykład zapisanie czegoś w ciasteczku. Jeśli pasuje urządzenie, zaloguj się automatycznie, a jeśli nie, zaloguj się. – brooks

+0

Dobra robota @LouisSimoneau! – josethernandezc

+3

Jeśli to robisz, warto zmienić ciąg 'en: devise: confirmations: confirmed' w pliku' config/locales/devise.en.yml', aby powiedzieć, że je również zalogowałeś ... –

15

Z nowszych wersjach opracować możesz wykonać następujące czynności.

config/routes.rb:

devise_for :users, controllers: { confirmations: 'users/confirmations' } 

app/controllers/users/confirmations_controller.rb:

class Users::ConfirmationsController < Devise::ConfirmationsController 
    def show 
    super do |resource| 
     sign_in(resource) 
    end 
    end 
end 
+0

Jestem prawie pewien, że to nie zadziała tak, jak zamierzano: wywołanie 'yield' w Devise's ConfirmationsController dzieje się tak, czy nie, zasób zawiera błędy, więc myślę, że to by Cię podpisało nawet bez odpowiedniego potwierdzenia token (!!!). –

+2

Tak, to się zaloguje bez względu na to, czy token jest ważny. Ale możesz temu zaradzić, zmieniając linię sign_in na 'sign_in (resource) if resource.errors.empty?' – scottwb

+0

W rzeczywistości nie podpisuje ona użytkownika, czy token jest ważny. To daje zasób, ale wszystkie pola są zerowe (ponieważ 'Devise' nie może znaleźć' użytkownika' z powiązanym tokenem). W rezultacie otrzymujesz przekierowanie do ścieżki sign_in (domyślnie) z komunikatem mówiącym, że musisz potwierdzić swoje konto. Teraz, z tym powiedziałem, myślę, że dodanie 'if resource.errors.empty?' Jest ładnie intencją ujawniającą, ale jest niepotrzebne. –

1

Chcieliśmy użytkownik więc zalogować się automatycznie, jeśli ona kliknie link w mailu, 2 godziny lub mniej po utworzeniu użytkownika. Na podstawie @ odpowiedź Sjor jest, wybraliśmy się z:

class ConfirmationsController < Devise::ConfirmationsController 
    def show 
    super do |resource| 
     if resource.confirmed_at > DateTime.now-2.hours && resource.errors.empty? 
     sign_in(resource) 
     end 
    end 
    end 
end 
3

Patrząc mb21 jest odpowiedzią powinno być

def show 
    super do |resource| 
    if resource.confirmation_sent_at > DateTime.now-2.hours && resource.errors.empty? 
     sign_in(resource) 
    end 
    end 
end 

confirmation_sent_at jest czas, wiadomość została wysłana do użytkownika, w przeciwieństwie do confirmed_at, który jest moment, w którym użytkownik kliknie link, który zawsze jest w ciągu 2 godzin od teraz na serwerze, kiedy to się stanie ...