Logowanie w aplikacji webowej

[info] Jeśli pracujesz na laboratorium, aby rozpocząć realizację kolejnego modułu, musisz wykonać poniższe operacje

  • sklonuj repozytorium ze swoim kodem (git clone ŚCIEŻKA_DO_REPOZYTORIUM),

  • zainstaluj potrzebne gemy (bundle install --path vendor/bundle),

  • dokonaj migracji bazy danych (rails db:migrate)

  • uruchom serwer (rails server)

Użytkownicy w naszym serwisie są już zapezpieczeni hasłem, ale nadal nie posiada on w swojej funkcjonalności logowania. Postarajmy się to nadrobić.

Zanim rozpoczniemy pracę nad logowaniem, dodajmy indeks bazy danych do numeru indeksu w modelu studenta.

  • rails generate migration AddIndexToStudentsIndex

class AddIndexToStudentsIndex < ActiveRecord::Migration[5.1]
  def change
    add_index :students, :index, unique: true
  end
end

Kontroler sesji

Podczas realizacji modułu o routingu, tworzyliśmy prosty kontroler statyczny, obsługujący jedną metodę. W wypadku logowania i kontroli sesji potrzebujemy trzech metod w nowym kontrolerze:

  • new — wyświetlającą panel logowania,

  • create — tworzącą nową sesję użytkownika,

  • destroy — usuwającą sesję użytkownika.

Na początek generujemy kontroler sesji:

  • rails generate controller sessions new

Następnie uzupełniamy routes o ścieżki do tworzenia i zamykania sesji i wskazujemy w nich odpowiednie akcje kontrolera. Upewnijmy się, że plik routes.rb wygląda jak poniżej.

Wygenerowanie kontrolera sesji z atrybutem new doda od razu do kontrolera metodę new i pusty widok, który zgodnie z zadeklarowanym routingiem możemy odwiedzić pod adresem http://localhost:3000/login. Uzupełnijmy ten widok o formularz logowania (app/views/sessions/new.html.erb).

Jeśli spróbujemy wysłać formularz, klikając w przycisk Zaloguj, uzyskamy błąd o braku akcji create. Dodajemy ją do kontrolera, z poziomu kodu renderując ten sam formularz, co przy logowaniu.

Wysłanie formularza już nie kończy się błędem, ale jeszcze nie pozwala na logowanie. Musimy je zaimplementować.

Najpierw lokalizujemy studenta po podanym numerze indeksu uzyskanym z formularza (Student.find_by(index: params[:session][:index])). Później, jeśli istnieje i autentykuje się do podanego hasła (student.authenticate()), logujemy go, w innym wypadku, wyświetlamy raz jeszcze formularz logowania (render 'new').

Działa? Tak. Tylko nie loguje, bo jeszcze tego nie przygotowaliśmy. Ale zrobimy to mądrze. Tak, żeby informacja o zalogowaniu nie była zamknięta tylko w jednym kontrolerze, ale dostępna z całej aplikacji. Tu pomogą helpery.

Helpery to osobne klasy zawierające tak zwane funkcje pomocnicze, które realizują logikę niepasującą ani do kontrolera ani do modelu. Scaffolding domyślnie tworzy pusty helper dla każdego kontrolera.

Otwieramy naczelny kontroler, ApplicationController. Inkludujemy w nim pomocnik (helper) kontrolera sesji.

Otwieramy SessionsHelper (app/helpers/sessions_helper.rb) i tworzymy w nim metodę log_in.

Na koniec uzupełniamy metodę create w kontrolerze, korzystając po poprawnej autentykacji ze stworonej w helperze metody log_in().

Próbujemy się zalogować, używając poprawnych danych. Sukces! Poprawne logowanie przenosi nas na stronę zalogowanego użytkownika. Wypadałoby jednak jakoś pamiętać tego studenta. Dodajmy więc do helpera metodę wskazującą zalogowanego studenta.

To jednak wysyłałoby zapytanie do bazy przy każdym pytaniu o studenta. Słabo. Zróbmy więc sprytne obejście.

Przy operatorze ||=, pole ustawi się tylko raz. Dodajmy też (do helpera) metodę sprawdzającą, czy ktoś jest zalogowany.

Edycja głównej formatki

Wśród widoków, w pliku app/views/layouts/application.html.erb znajduje się naczelna formatka naszej aplikacji. Wysyłając do przeglądarki użytkownika jakikolwiek widok, w zasadzie wstawiamy go do niej, w miejsce pola yield.

Możemy uzupełnić naszą główną formatkę o elementy widoku obecne na każdej podstronie. Na początek dodajmy do niej brzydki nagłówek, informujący o tym, czy jakiś użytkownik jest aktualnie zalogowany.

Jeśli w poprzednim kroku udało nam się poprawnie zaimplementować logowanie, na ekranie powinna pojawić się odpowiednia informacja.

Po usunięciu ciasteczek informacja powinna zmienić się na Wylogowany. Wydaje się jednak, że usuwanie ciasteczek to raczej mało wygodna forma wylogowywania się z jakiegoś serwisu. Rozbudujmy więc odrobinę nagłówek, aby pojawiło się w nim łącze do logowania/wylogowywania.

Możemy się teraz spokojnie ponownie zalogować. Pozostało wylogowywanie. Zaczniemy od metody helpera, która usunie informację o sesji i aktualnie zalogowanym studencie.

Później wykorzystajmy ją w metodzie destroy kontrolera.

Przetestujmy logowanie. Gratulacje! Dostęp do naszej aplikacji został jakkolwiek zabezpieczony hasłem.

[info] Aktualny kod

Na koniec każdego modułu znajduje się łącze do pełnej wersji kodu, który powinien być jego wynikiem.

Last updated