In diesem Revisit schauen wir uns die Benutzer-Authentifizierung mit bcrypt noch einmal an – diesmal mit der aktuellen Version 0.4.2 des b4um Generators.
Seit unserem ursprünglichen Tutorial hat sich einiges verändert. Der Generator übernimmt inzwischen deutlich mehr Arbeit: Er erkennt password_digest, richtet has_secure_password ein, berücksichtigt Passwortfelder in Formularen und Tests und kann anschließend eine vollständige Session-basierte Authentifizierung erzeugen.
Wir erstellen einen Benutzer mit Name, E-Mail-Adresse und Passwort, richten Login und Logout ein und schützen anschließend Bereiche unserer Anwendung vor nicht angemeldeten Benutzern.
Voraussetzungen
Wir verwenden eine Rails-Anwendung, in der der b4um Generator installiert ist.
In der Gemfile befindet sich:
gem "b4um_generators", "~> 0.4.2"
Danach installieren wir die Abhängigkeiten:
bundle install
Falls der b4um Generator in diesem Projekt noch nicht eingerichtet wurde, starten wir zunächst den Installations-Wizard:
bin/rails generate b4um:install
Während der Installation fragt uns der Generator unter anderem, ob bcrypt verwendet werden soll.
Hier wählen wir:
Install bcrypt authentication support? (y/n)
y
Damit steht bcrypt für unsere spätere Benutzer-Authentifizierung zur Verfügung.
Installation mit bcrypt
Benutzer erstellen
Als Nächstes benötigen wir ein Benutzer-Modell.
Unser Benutzer erhält einen Namen, eine E-Mail-Adresse und einen password_digest.
legen wir gleichzeitig fest, dass Name und E-Mail-Adresse Pflichtfelder sind.
Anschließend führen wir die erzeugte Migration aus:
bin/rails db:migrate
Der entscheidende Punkt ist dabei password_digest.
Wir erzeugen keine Datenbankfelder namens password oder password_confirmation. bcrypt speichert das eingegebene Passwort nicht im Klartext. In der Datenbank befindet sich lediglich der daraus erzeugte Passwort-Hash in password_digest.
password und password_confirmation werden später über has_secure_password bereitgestellt.
Was hat der Generator im User-Modell erzeugt?
Öffnen wir:
app/models/user.rb
Der Generator erkennt das Feld password_digest und richtet die bcrypt-Unterstützung für das Modell ein.
Ein wichtiger Bestandteil ist:
has_secure_password
Außerdem haben wir über --required=name,email unsere Pflichtfelder definiert.
Entsprechend enthält das Modell unter anderem Validierungen für diese Attribute.
has_secure_password stellt uns unter anderem die virtuellen Attribute
password
password_confirmation
zur Verfügung.
Diese müssen nicht als Spalten in der Datenbank existieren.
Das eingegebene Passwort wird von bcrypt verarbeitet und als Hash in password_digest gespeichert.
User-Modell in VS Code
Das Benutzerformular
Auch das Formular berücksichtigt die Passwort-Authentifizierung.
Öffnen wir:
app/views/users/_form.html.erb
Dort finden wir die entsprechenden Passwortfelder.
Für den Benutzer sieht das später wie eine normale Passwort-Eingabe aus. Intern landet das Passwort jedoch nicht direkt in unserem User-Datensatz.
Registrierungsformular im Browser leer
Registrierungsformular im Browser gefüllt
Damit können wir bereits einen Benutzer erstellen.
Wir legen für das Tutorial einen Testbenutzer an.
Beispielsweise:
Name: Max Mustermann
E-Mail: max@example.com
Passwort: ********
Passwortbestätigung: ********
Nach dem Speichern existiert unser erster Benutzer – aber wir haben noch keine eigentliche Anmeldung.
Genau darum kümmert sich der Authentication-Generator.
Authentication erzeugen
Jetzt kommt der zentrale Schritt dieses Revisits.
Wir führen aus:
bin/rails generate b4um:authentication User
Damit weiß der Generator, dass User unser Authentifizierungsmodell ist.
Der Authentication-Generator richtet die benötigte Session-Authentifizierung ein.
Dazu gehören unter anderem:
Login und Logout
Session-Verwaltung
current_user
logged_in?
require_login
die entsprechenden Routen
Login-Formular und Session-Controller
Anpassungen für die generierten Tests
Authentication-Generator
Wie funktioniert die Anmeldung?
Die Authentifizierung basiert auf einer Rails-Session.
Nach erfolgreicher Anmeldung wird die ID des Benutzers in der Session gespeichert.
Sinngemäß:
session[:user_id] = user.id
Dadurch muss Rails nicht bei jedem Seitenaufruf erneut nach E-Mail-Adresse und Passwort fragen.
Im ApplicationController stellt uns der Generator die benötigten Helfermethoden zur Verfügung.
Öffnen wir:
app/controllers/application_controller.rb
Dort finden wir unter anderem:
helper_method :current_user, :logged_in?
sowie die Methoden:
current_user
logged_in?
require_login
current_user ermittelt den momentan angemeldeten Benutzer anhand der Session.
logged_in? beantwortet die Frage, ob aktuell ein Benutzer angemeldet ist.
Und require_login können wir verwenden, wenn bestimmte Bereiche nur für angemeldete Benutzer erreichbar sein sollen.
Authentication im ApplicationController
Das Login-Formular
Jetzt können wir unsere Login-Seite öffnen.
Die entsprechende Route lautet:
/login
Hier geben wir die E-Mail-Adresse und das Passwort unseres zuvor angelegten Benutzers ein.
Login-Seite
Login-Seite
Nach erfolgreicher Anmeldung wird die Session gesetzt und der Benutzer zur Anwendung weitergeleitet.
Die Navigation kann jetzt abhängig vom Login-Status unterschiedliche Elemente darstellen.
Beispielsweise können für einen nicht angemeldeten Benutzer Registrierungs- und Login-Möglichkeiten angezeigt werden, während ein angemeldeter Benutzer Zugriff auf sein Profil und den Logout erhält.
Anwendung nach dem Login
Logout
Zur vollständigen Authentifizierung gehört natürlich auch das Abmelden.
Beim Logout wird die Benutzer-ID aus der Session entfernt.
Danach gilt wieder:
logged_in?
# => false
und:
current_user
# => nil
Der Benutzer muss sich erneut mit seiner E-Mail-Adresse und seinem Passwort anmelden, um wieder auf geschützte Bereiche zugreifen zu können.
Navigation nach Logout
Bereiche vor Gästen schützen
Bis jetzt haben wir Authentication eingerichtet, aber möglicherweise dürfen nicht angemeldete Besucher weiterhin Controller-Aktionen aufrufen.
Dafür besitzt der Authentication-Generator die Option:
--protect
Nehmen wir beispielsweise an, unsere Anwendung besitzt einen ProductsController.
Dann können wir Authentication erneut mit einem geschützten Controller aufrufen:
bin/rails generate b4um:authentication User --protect=products
Der Generator ergänzt im ProductsController den entsprechenden Schutz.
Dabei bleiben beispielsweise öffentliche Ansichten wie index und show erreichbar, während Aktionen zum Erstellen, Bearbeiten oder Löschen eine Anmeldung verlangen.
Ein Besucher kann damit weiterhin die Produktübersicht und einzelne Produkte ansehen.
Versucht er jedoch beispielsweise die Seite zum Erstellen eines neuen Produkts aufzurufen, wird er zur Anmeldung weitergeleitet.
Geschützter Controller in VS Code
Product show
Was übernimmt der b4um Generator heute für uns?
Genau hier liegt der wesentliche Unterschied zum älteren Authentication-Tutorial.
Wir müssen die einzelnen Bestandteile nicht mehr manuell zusammensetzen.
Der Scaffold- und Authentication-Generator arbeiten miteinander zusammen.
Bei einem Benutzer mit:
password_digest:string
wird die bcrypt-basierte Passwortverwaltung berücksichtigt.
Der Authentication-Generator ergänzt anschließend die Session-basierte Anmeldung und die benötigten Helfermethoden.
Mit --protect können wir darüber hinaus festlegen, welche Bereiche unserer Anwendung eine Anmeldung voraussetzen.
Dadurch besteht die Authentifizierung nicht aus einer Sammlung einzelner Code-Snippets, die wir selbst miteinander verbinden müssen. Die Generatoren erzeugen eine zusammenhängende Grundlage, die wir anschließend an unsere Anwendung anpassen können.
Sicherheit: Das Passwort wird nicht gespeichert
Ein besonders wichtiger Punkt ist die Passwortspeicherung.
Wenn ein Benutzer beispielsweise folgendes Passwort eingibt:
MeinGeheimesPasswort
landet dieser Text nicht in der Datenbank.
bcrypt erzeugt daraus einen Passwort-Hash, der in:
password_digest
gespeichert wird.
Beim späteren Login wird das eingegebene Passwort gegen diesen Hash geprüft.
Damit kann unsere Anwendung einen Benutzer authentifizieren, ohne dessen ursprüngliches Passwort speichern zu müssen.
Fazit
Mit bcrypt und dem b4um Generator 0.4.2 können wir eine vollständige Grundlage für die Benutzer-Authentifizierung unserer Rails-Anwendung erzeugen.
Der Scaffold-Generator berücksichtigt password_digest und richtet die notwendigen Bestandteile für has_secure_password ein. Der Authentication-Generator ergänzt anschließend Login, Logout, Sessions und die Helfermethoden für den aktuellen Benutzer.
Über --protect lassen sich außerdem Bereiche unserer Anwendung gezielt auf angemeldete Benutzer beschränken.
Damit haben wir gleichzeitig die Grundlage für den nächsten Schritt geschaffen.
Denn bisher unterscheiden wir lediglich zwischen:
nicht angemeldet und angemeldet.
In vielen Anwendungen benötigen wir zusätzlich Benutzer mit erweiterten Rechten.
Genau darum geht es im nächsten Tutorial:
Administratorverwaltung mit dem b4um Generator
Dort erweitern wir unsere bestehende Authentication um Administratoren, schützen den Adminbereich und verwalten Benutzer direkt über eine generierte Admin-Oberfläche.
Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren,
Funktionen für soziale Medien anbieten zu können und die Zugriffe auf
unsere Website zu analysieren.
Sie akzeptieren unsere Cookies, wenn Sie fortfahren diese Webseite zu
nutzen.
Datenschutzerklärung.