Django Authentifizierung: Eine Reise mit zwei Pfaden
Grace Collins
Solutions Engineer · Leapcell

Einleitung
In der Welt der Webentwicklung ist die Benutzerauthentifizierung für fast jede Anwendung eine nicht verhandelbare Funktion. Von einfachen Blogs bis zu komplexen E-Commerce-Plattformen ist die sichere Verwaltung von Benutzerzugriff, Rollen und Profilen von größter Bedeutung. Django, ein "Webframework für Perfektionisten mit Fristen", bietet ein unglaublich robustes und flexibles Authentifizierungssystem. Wenn die Anwendungen jedoch an Komplexität gewinnen und einzigartige Anforderungen entstehen, stehen Entwickler oft vor einer kritischen Entscheidung: Sollen sie am integrierten User
-Modell von Django festhalten oder sich in den Bereich benutzerdefinierter Benutzermodelle wagen, um ihren Bedürfnissen besser gerecht zu werden? Dieser Artikel befasst sich mit den Nuancen beider Ansätze und bietet einen umfassenden Leitfaden, der Ihnen helfen soll, fundierte Entscheidungen bei der Architektur Ihrer Django-Anwendungen zu treffen.
Die Kernkonzepte der Django-Authentifizierung
Bevor wir uns mit der vergleichenden Analyse befassen, wollen wir ein gemeinsames Verständnis der Kernkomponenten schaffen, die in das Authentifizierungssystem von Django eingebunden sind.
User
-Modell: Dies ist das zentrale Stück, das einen einzelnen Benutzer Ihrer Anwendung darstellt. Es speichert Anmeldeinformationen (wie Benutzername und Passwort-Hashes) und grundlegende identifizierende Informationen.- Authentifizierungs-Backends: Dies sind Klassen, die den eigentlichen Authentifizierungsprozess handhaben (z. B. Überprüfung eines Benutzernamens und Passworts gegen die Datenbank). Django verfügt standardmäßig über ein Backend, das gegen das
User
-Modell authentifiziert. AUTH_USER_MODEL
-Einstellung: Eine wichtige Django-Einstellung, die angibt, welches Modell als Benutzermodell Ihrer Anwendung verwendet werden soll. Standardmäßig ist es aufauth.User
eingestellt.- Berechtigungen und Gruppen: Das Authentifizierungssystem von Django erstreckt sich auch auf die Autorisierung, sodass Sie Berechtigungen (z. B. "kann Beitrag bearbeiten") definieren und Benutzer zu Rollen (z. B. "Redakteure") gruppieren können, um die Zugriffskontrolle zu verwalten.
Nun wollen wir die beiden Hauptpfade für die Verwaltung von Benutzern in Django untersuchen.
Django's integriertes Authentifizierungssystem
Das Standard-Benutzermodell von Django, django.contrib.auth.models.User
, ist eine leistungsstarke und gut getestete Lösung, die in den meisten Django-Projekten vorkonfiguriert ist. Es ist oft der beste Ausgangspunkt für viele Anwendungen, da es sofort verfügbar und umfassend ist.
Funktionen und Vorteile
- Sofort einsatzbereit: Keine Einrichtung erforderlich. Erstellen Sie Superuser und beginnen Sie mit der Authentifizierung.
- Robust und sicher: Profitiert von jahrelanger Überprüfung durch die Community, Fehlerbehebungen und Sicherheitsverbesserungen. Behandelt Passwort-Hashing, Salting, Sitzungsverwaltung und mehr.
- Admin-Integration: Nahtlose Integration in die Django Admin Oberfäche, wodurch Administratoren Benutzer und Gruppen mit minimalem Aufwand verwalten können.
- Umfassende Funktionalität: Enthält Felder für
username
,password
,email
,first_name
,last_name
,is_staff
,is_active
,is_superuser
,last_login
unddate_joined
. - Passwort-Reset-Funktionalität: Django bietet integrierte Ansichten und Formulare zur Handhabung von Passwort-Resets, die von Grund auf schwierig korrekt und sicher zu implementieren sind.
Wann er verwendet werden sollte
Das integrierte User
-Modell ist eine ausgezeichnete Wahl für:
- Die meisten Standard-Webanwendungen: Wenn Ihre Benutzeranforderungen mit den standardmäßig bereitgestellten Feldern übereinstimmen.
- Schnelles Prototyping: Ein Authentifizierungssystem schnell zum Laufen bringen.
- Anwendungen, bei denen Benutzerprofile minimal sind: Wenn zusätzliche Benutzerdaten über Eins-zu-Eins-Beziehungen zum
User
-Modell verwaltet werden (z. B.UserProfile
-Modell).
Beispiel: Verwendung des integrierten Benutzers
Nehmen wir an, Sie möchten einen Post
mit einem Autor verknüpfen. Mit dem integrierten User
-Modell ist dies unkompliziert:
# myapp/models.py from django.db import models from django.contrib.auth.models import User # Importiere den integrierten User class Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) # Direkter Fremdschlüssel created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title # Beispielhafte Nutzung in einer Django-Ansicht oder Shell: # from django.contrib.auth.models import User # from myapp.models import Post # # user = User.objects.create_user(username='john_doe', password='securepassword') # post = Post.objects.create(title='Mein erster Beitrag', content='Hallo, Welt!', author=user)
Benutzerdefinierte Benutzermodelle
Obwohl das integrierte User
-Modell leistungsstark ist, passt es möglicherweise nicht immer zu allen Anforderungen. Oft benötigen Anwendungen spezifischere benutzerspezifische Daten (z. B. phone_number
, date_of_birth
, user_type
, avatar
) oder sie bevorzugen einen anderen Authentifizierungsidentifikator (z. B. E-Mail anstelle von Benutzername). Hier glänzen benutzerdefinierte Benutzermodelle. Django bietet zwei Hauptmöglichkeiten, das User
-Modell anzupassen: durch Erweitern von AbstractUser
oder durch Erweitern von AbstractBaseUser
.
AbstractUser
AbstractUser
ist eine Unterklasse von AbstractBaseUser
und bietet eine Implementierung des vollständigen User
-Modells, einschließlich aller Standardfelder (username
, email
, first_name
, last_name
, is_staff
, is_active
, is_superuser
, last_login
, date_joined
). Sie können beliebige zusätzliche Felder, Methoden oder Manager hinzufügen, die Sie benötigen. Dies ist der empfohlene Ansatz für die meisten benutzerdefinierten Benutzermodelle, wenn Sie die Standard-Benutzerfelder von Django beibehalten möchten.
AbstractBaseUser
AbstractBaseUser
bietet die Kernimplementierung eines Benutzermodells, einschließlich gehashter Passwörter und tokenisierter Passwort-Resets. Es enthält keine weiteren Felder. Wenn Sie dies verwenden, müssen Sie alle für Ihr Benutzermodell erforderlichen Felder definieren, einschließlich dessen, wie es sich identifiziert (z. B. email
anstelle von username
). Sie müssen auch REQUIRED_FIELDS
und ein USERNAME_FIELD
definieren. Dieser Ansatz bietet maximale Flexibilität, erfordert aber auch mehr Arbeit.
Wann benutzerdefinierte Benutzermodelle verwendet werden sollten
- Hinzufügen eindeutiger Benutzerfelder: Wenn Ihre Anwendung zusätzliche Benutzerattribute benötigt, die im integrierten
User
-Modell nicht vorhanden sind (z. B.phone_number
,date_of_birth
,company_id
). - Ändern des Authentifizierungsidentifikators: Wenn Benutzer sich mit ihrer E-Mail-Adresse anstelle eines Benutzernamens anmelden sollen.
- Ändern des Kernbenutzerverhaltens: Wenn Sie stark anpassen müssen, wie Benutzer verwaltet, erstellt oder identifiziert werden.
- Vermeiden von Eins-zu-Eins-Profil-Modellen: Anstatt ein
UserProfile
-Modell zu erstellen, das mit dem integriertenUser
verknüpft ist, können Sie alle Benutzerdaten direkt in Ihr benutzerdefiniertes Benutzermodell einfügen.
Beispiel: Erweitern von AbstractUser
Erstellen wir ein benutzerdefiniertes Benutzermodell, das sich per E-Mail authentifiziert und ein phone_number
-Feld enthält.
# myapp/models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # Füge hier deine zusätzlichen Felder hinzu phone_number = models.CharField(max_length=15, blank=True, null=True) # email ist bereits von AbstractUser bereitgestellt, aber wir möchten, dass es das USERNAME_FIELD ist # Wir möchten auch, dass email eindeutig ist email = models.EmailField(unique=True) # Wir weisen Django an, das E-Mail-Feld für die Authentifizierung zu verwenden USERNAME_FIELD = 'email' # REQUIRED_FIELDS werden beim Erstellen eines Benutzers über createsuperuser abgefragt # Diese Felder müssen zusätzlich zum USERNAME_FIELD und Passwort vorhanden sein # Achte darauf, das USERNAME_FIELD oder das Passwort hier nicht aufzulisten REQUIRED_FIELDS = ['username'] # Wir möchten trotzdem einen Benutzernamen abfragen def __str__(self): return self.email # In settings.py musst du unbedingt dein benutzerdefiniertes Benutzermodell angeben: # AUTH_USER_MODEL = 'myapp.CustomUser'
Wichtiger Hinweis: Die Einstellung AUTH_USER_MODEL
muss festgelegt werden, bevor Sie irgendwelche Migrationen durchführen (d. h. bevor Sie python manage.py migrate
ausführen) für Ihr Projekt. Wenn Sie sich nach bereits durchgeführten Migrationen mit dem Standard auth.User
für ein benutzerdefiniertes Benutzermodell entscheiden, ist dies ein erheblich komplexerer Prozess und erfordert in der Regel eine sorgfältige Datenmigration oder einen Neuanfang.
Beispiel: Erweitern von AbstractBaseUser
Dieser Ansatz ist für diejenigen gedacht, die die vollständige Kontrolle wünschen und ihr Benutzermodell fast von Grund auf neu erstellen.
# myapp/models.py from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager from django.db import models from django.utils import timezone class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('Das E-Mail-Feld muss gesetzt sein') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser muss is_staff=True haben.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser muss is_superuser=True haben.') return self.create_user(email, password, **extra_fields) class MinimalUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) first_name = models.CharField(max_length=30, blank=True) last_name = models.CharField(max_length=30, blank=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) date_joined = models.DateTimeField(default=timezone.now) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name'] objects = CustomUserManager() def __str__(self): return self.email def get_full_name(self): return f"{self.first_name} {self.last_name}".strip() def get_short_name(self): return self.first_name # In settings.py: # AUTH_USER_MODEL = 'myapp.MinimalUser'
In diesem MinimalUser
-Beispiel mussten wir:
- Alle grundlegenden Felder definieren (
email
,first_name
,last_name
,is_active
,is_staff
,date_joined
). - Von
PermissionsMixin
erben, um die Felderis_superuser
,groups
unduser_permissions
zu erhalten. USERNAME_FIELD
als'email'
definieren.REQUIRED_FIELDS
fürcreatesuperuser
definieren.- Einen benutzerdefinierten
UserManager
(CustomUserManager
) erstellen, um die Benutzer- und Superuser-Erstellung zu handhaben, einschließlich der E-Mail-Normalisierung.
Wie Sie sehen, erfordert dies erheblich mehr Boilerplate-Code, liefert aber die vollständige Kontrolle über das Schema und den Erstellungsprozess des Benutzermodells.
Migration zwischen Benutzermodellen
Es ist von größter Bedeutung, hervorzuheben, dass die Änderung von AUTH_USER_MODEL
nach den ersten Migrationen ein nicht triviales Unterfangen ist. Wenn Sie mit dem integrierten User
beginnen und später entscheiden, dass Sie ein benutzerdefiniertes benötigen, stehen Sie vor einer erheblichen Herausforderung. Sie müssen in der Regel:
- Ihr benutzerdefiniertes Benutzermodell erstellen.
- Eine Migrationsdatei manuell erstellen, um Daten vom alten
auth.User
-Tabellen in Ihre neue benutzerdefinierte Modelle-Tabelle zu migrieren. - Alle Fremdschlüssel, die auf
auth.User
verweisen, sorgfältig aktualisieren, damit sie auf IhrAUTH_USER_MODEL
verweisen. - Alle Migrationen der
auth
-App und möglicherweise dieauth_user
-Tabelle selbst entfernen, wenn Sie sichergestellt haben, dass alle Verweise aktualisiert wurden.
Dieser Prozess ist fehleranfällig und kann bei nicht sorgfältiger Ausführung zu Datenverlust führen. Daher wird immer empfohlen, Ihr Benutzermodell zu Beginn eines Projekts zu entscheiden, noch bevor Sie die ersten makemigrations
- und migrate
-Befehle ausführen.
Fazit
Sowohl das integrierte User
-Modell von Django als auch benutzerdefinierte Benutzermodelle bieten robuste Lösungen für die Authentifizierung, jede mit ihren eigenen Vorteilen und Anwendungsfällen. Das integrierte Modell ist eine sichere, effiziente und sofort verfügbare Option für Anwendungen mit Standard-Benutzeranforderungen und bietet schnelle Entwicklung und robuste Sicherheit out-of-the-box. Wenn Ihre Anwendung einzigartige Benutzerattribute, benutzerdefinierte Authentifizierungsidentifikatoren (wie E-Mail-basierte Anmeldungen) oder mehr granulare Kontrolle über die Benutzerverwaltung erfordert, ist die Implementierung eines benutzerdefinierten Benutzermodells, idealerweise durch Erweitern von AbstractUser
, die bessere Wahl. Diese Entscheidung, die idealerweise zu Beginn des Projekts getroffen wird, bestimmt die Flexibilität und Skalierbarkeit Ihres Benutzerverwaltungssystems. Letztendlich ermöglicht Ihnen die richtige Wahl, sichere und anpassungsfähige Django-Anwendungen zu erstellen, die die Bedürfnisse Ihrer Benutzer perfekt erfüllen.