Django-de

Django Dokumentation

Benutzer-Authentifizierung in Django

Diese Dokumentation gilt für Djangos Entwicklerversion, die zum Teil erhebliche Unterschiede zur letzten veröffentlichen Version aufweist.

Django wird mit einem Benutzer-Authentifizierungssystem geliefert. Es verwaltet Benutzer-Accounts, Gruppen, Berechtigungen und Cookie-basierte Benutzer-Sessions. Dieses Dokument erklärt, wie diese Dinge funktionieren.

Überblick

Das Authentifizierungssystem besteht aus:

  • Benutzer (Users)
  • Berechtigungen (Permissions): Binäre Markierungen (ja/nein) bestimmen, ob der Benutzer eine bestimmte Aufgabe ausführen darf.
  • Gruppen (Groups): Eine allgemeine Möglichkeit, um Bezeichnungen und Berechtigungen auf mehr als einen Benutzer anzuwenden.
  • Mitteilungen (Messages): Ein einfacher Weg, bestimmten Benutzern Mitteilungen zukommen zu lassen.

Installation

Die Authentifizierungsfunktion ist als eine Django-Anwendung in django.contrib.auth eingebunden. Es ist einfach, sie zu installieren:

  1. Füge 'django.contrib.auth' zu deiner INSTALLED_APPS Einstellung hinzu.
  2. Führe den Befehl manage.py syncdb aus.

Beachte, dass die Standard-settings.py-Datei, die von django-admin.py startproject erstellt wird, der Einfachheit halber bereits 'django.contrib.auth' unter INSTALLED_APPS enthält. Wenn INSTALLED_APPS bei dir bereits 'django.contrib.auth' enthält, kannst du manage.py syncdb ohne weiteres erneut ausführen. Du kannst diesen Befehl so oft ausführen wie du magst, es wird jedes mal nur das installieren, was benötigt wird.

Der Befehl syncdb erzeugt die nötigen Datenbanktabellen, erstellt die Berechtigungen für alle Anwendungen, die sie benötigen und fordert dich auf, einen Superuser-Account anzulegen, wenn du den Befehl zum ersten Mal ausführst.

Sobald du dieses Schritte ausgeführt hast, war es das auch schon.

Benutzer

Benutzer werden von einem Standard-Django-Datenmodell dargestellt, das sich in django/contrib/auth/models.py befindet.

API-Referenz

Felder

User-Objekte haben die folgenden Felder:

  • username – Erforderlich. 30 Zeichen oder weniger. Nur alphanumerische Zeichen (Buchstaben, Zahlen und Unterstrich).
  • first_name – Optional. 30 Zeichen oder weniger.
  • last_name – Optional. 30 Zeichen oder weniger.
  • email – Optional. E-Mail-Adresse.
  • password – Erforderlich. Ein Hash des Passwortes, sowie Meta-Daten. (Django speichert Passwörter nicht unverschlüsselt ab). Die unverschlüsselten Passwörter können beliebig lang sein und jedes Zeichen enthalten. Erfahre mehr im Abschnitt “Passwörter” unten.
  • is_staff – Boolean. Legt fest, ob dieser Benutzer Zugriff zur Administrationsoberfläche hat.
  • is_active – Boolean. Legt fest, ob das Konto zum Anmelden benutzt werden kann. Setze diese Markierung auf False, statt das Konto zu löschen.
  • is_superuser – Boolean. Legt fest, dass dieser Benutzer alle Berechtigungen hat, ohne sie explizit zuweisen zu müssen.
  • last_login – Datum und Zeit der letzten Anmeldung. Dieses ist standardmäßig auf das aktuelle Datum und die Zeit gesetzt.
  • date_joined – Datum und Zeit, zu der das Konto erstellt wurde. Dieses wird standardmäßig auf das aktuelle Datum und die Zeit gesetzt, wenn das Konto erstellt wird.

Methoden

User-Objekte haben zwei Many-to-Many-Felder (n-m): groups und user_permissions. User-Objekte können auf ihre verwandten Objekte auf die gleiche Weise wie alle anderen Django-Datenmodelle zugreifen:

myuser.groups = [group_list]
myuser.groups.add(group, group,...)
myuser.groups.remove(group, group,...)
myuser.groups.clear()
myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...]
myuser.user_permissions.clear()

Zusätzlich zu diesen automatischen API-Methoden, haben User-Objekte die folgenden speziellen Methoden:

  • is_anonymous() – Gibt immer False zurück. Dies ist eine Möglichkeit zwischen User- und AnonymousUser-Objekten zu unterscheiden. Im Allgemeinen solltest du is_authenticated() dieser Methode vorziehen.

  • is_authenticated() – Gibt immer True zurück. Dies ist eine Möglichkeit zu ermitteln, ob der Benutzer authentifiziert wurde. Dies bezieht keine Berechtigungen ein und prüft nicht, ob der Benutzer aktiv ist - gibt nur an, dass der Benutzer einen korrekten Benutzername und ein Passwort benutzt hat.

  • get_full_name() – Gibt den first_name und den last_name zurück, mit einem Leerzeichen dazwischen.

  • set_password(raw_password) – Setzt das Passwort des Benutzers auf den angegebenen unverschlüsselten String und kümmert sich um das verschlüsseln. Speichert nicht das User-Objekt.

  • check_password(raw_password) – Gibt True zurück, wenn der eingegebene unverschlüsselte String das richtige Passwort für den Benutzer ist (Dieses kümmert sich um das Verschlüsseln des Passwortes und das Vergleichen).

  • set_unusable_password()Neu in Djangos Entwicklerversion. Markiert den Benutzer so, als ob er kein Passwort vergeben hat. Dies ist nicht das Gleiche wie ein leerer String als Passwort. check_password() mit diesen Benutzer gibt niemals True zurück. Speichert nicht das User-Objekt.

    Möglicherweise brauchst du diese Methode, wenn die Authentifizierung für deine Anwendung gegen eine bestehende Datenquelle, wie ein LDAP-Verzeichnis, ausgeführt wird.

  • has_usable_password()Neu in Djangos Entwicklerversion. Gibt ein False zurück, wenn set_unusable_password() für diesen Benutzer aufgerufen wurde.

  • get_group_permissions() – Gibt eine Liste mit Berechtigungen zurück, die der Benutzer in seiner/ihrer Gruppe hat.

  • get_all_permissions() – Gibt eine Liste mit Berechtigungen zurück, die der Benutzer hat, sowohl in der Gruppe, als auch Benutzerrechte.

  • has_perm(perm) – Gibt True zurück, wenn der Benutzer eine bestimmte Berechtigung hat, bei dem das Format 'package.codename' ist. Wenn der Benutzer inaktiv ist, gibt diese Methode immer False zurück.

  • has_perms(perm_list) – Gibt True zurück, wenn der Benutzer jedes der festgelegten Rechte hat, bei dem das Format ‘package.codename' ist. Wenn der Benutzer inaktiv ist, gibt diese Methode immer False zurück.

  • has_module_perms(package_name) – Gibt True zurück, wenn der Benutzer irgendeine Berechtigung des angegebenen Paketes hat (das Django Anwendungs-Label). Wenn der Benutzer inaktiv ist, gibt diese Methode immer ein False zurück.

  • get_and_delete_messages() – Gibt eine Liste von Message-Objekten aus der Warteschlange des Benutzers zurück und löscht die Mitteilungen aus der Warteschlange.

  • email_user(subject, message, from_email=None) – Sendet eine E-Mail an den Benutzer. Wenn from_email None ist, benutzt Django die Einstellungswerte von DEFAULT_FROM_EMAIL.

  • get_profile() – Gibt ein seitenspezifisches Profil für diesen Benutzer zurück. Verursacht ein django.contrib.auth.models.SiteProfileNotAvailable, wenn die aktuelle Seite keine Profile zulässt. Für Informationen, wie man ein seitenspezifisches Benutzerprofil definiert, siehe den Abschnitt über Speicherung von zusätzlichen Benutzerinformationen unten.

Manager-Funktionen

Das User-Datenmodell hat einen benutzerdefinierten Manager, der die folgenden Hilfsfunktionen hat:

  • create_user(username, email, password=None) – Erzeugt, speichert und gibt einen User zurück. username, email und password werden eingestellt, wie eingegeben. Der User bekommt ein is_active=True.

    Wenn kein Passwort bereitgestellt wird, wird set_unusable_password() aufgerufen.

    Siehe Benutzer erzeugen für eine beispielhafte Benutzung.

  • make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') – Gibt ein zufälliges Passwort mit der angegebenen Länge und den ausgewählten erlaubten Zeichen zurück (Beachte, dass der Standardwert von allowed_chars keine Zeichen enthält, die verwechselt werden können, darunter z. B. 1, I und 0).

Grundlegende Benutzung

Benutzer erzeugen

Die einfachste Möglichkeit Benutzer anzulegen, ist die Benutzung der mitgelieferten create_user-Hilfsfunktion:

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# An diesem Punkt ist der Benutzer ein Objekt, das schon in die Datenbank
# gespeichert wurde. Du kannst damit fortfahren seine Attribute zu
# ändern, wenn du andere Felder ändern willst.
>>> user.is_staff = True
>>> user.save()

Passwörter ändern

Ändere ein Passwort mit set_password():

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username__exact='john')
>>> u.set_password('new password')
>>> u.save()

Setze das password-Attribut nicht direkt, außer du weißt, was du machst. Dies wird in dem nächsten Abschnitt erklärt.

Passwörter

Das password-Attribut eines user-Objektes ist ein String in diesem Format:

hashtype$salt$hash

Das sind hashtype, salt und hash, getrennt durch ein Dollar-Zeichen.

Hashtype ist entweder sha1 (Standard), md5 oder crypt – der Algorithmus wird benutzt, um einen einseitigen Hash eines Passwortes durchzuführen. Salt ist ein zufälliger String, der benutzt wird, um aus dem unverschlüsselten Passwort einen Hash zu erzeugen. Beachte, dass die crypt-Methode nur von Plattformen unterstützt wird, die das Standard-Python crypt-Modul verfügbar haben, und dass crypt nur in der Django-Entwicklerversion verfügbar ist.

Zum Beispiel:

sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4

Die User.set_password()- und User.check_password()-Funktionen verwalten die Einstellungen und überprüfen die Werte hinter den Kulissen.

Vorherige Django-Versionen, wie 0.90, benutzten einen einfachen MD5-Hash ohne Passwort-Salt und werden für die Rückwärtskompabilität immer noch unterstützt. Sie werden automatisch in den neuen Stil konvertiert, wenn User.check_password() für einen bestimmten Benutzer zum ersten Mal korrekt arbeitet.

Anonyme Benutzer

django.contrib.auth.models.AnonymousUser ist eine Klasse, die das django.contrib.auth.models.User-Interface implementiert, mit folgenden Unterschieden:

  • id ist immer None.
  • is_staff und is_superuser sind immer False.
  • is_active ist immer True.
  • groups und user_permissions sind immer leer.
  • is_anonymous() gibt True anstelle von False zurück.
  • is_authenticated() gibt False anstelle von True zurück.
  • has_perm() gibt immer False zurück.
  • set_password(), check_password(), save(), delete(), set_groups() und set_permissions() erzeugen NotImplementedError.

In der Anwendung wirst du wahrscheinlich AnonymousUser-Objekte selber nicht benötigen. Sie werden aber von Web-Anfragen benutzt, wie im nächsten Abschnitt erklärt wird.

Superuser erstellen

manage.py syncdb fordert dich auf, einen Superuser anzulegen, wenn du es zum ersten Mal ausführst, nachdem du 'django.contrib.auth' zu deinen INSTALLED_APPS hinzufügt hast. Wenn du später einen Superuser auf der Kommandozeile erzeugen musst, kannst du das Dienstprogramm create_superuser.py benutzen. Führe einfach diesen Befehl aus:

python /path/to/django/contrib/auth/create_superuser.py

Stelle sicher, dass du /path/to/ mit dem Pfad zum Django-Code in deinem Dateisystem ersetzt.

Zusätzliche Informationen über Benutzer speichern

Wenn du zusätzliche Informationen für deine Benutzer speichern möchtest, bietet Django für diesen Zweck eine Methode an, um ein seitenspezifisches Datenmodell – “Benutzerprofil” genannt – zu spezifizieren.

Um diese Funktion zu nutzen, musst du ein Datenmodell mit Feldern für die zusätzlichen Informationen definieren oder weitere Methoden anlegen, die verfügbar sein sollen. Füge auch einen ForeignKey Feld zu diesem Datenmodell hinzu, dass auf das User-Datenmodell zeigt. Achte darauf, dass du dabei unique=True festlegst, damit nur eine Instanz deines Datenmodells für jeden Benutzer erzeugt werden kann.

Um zu kennzeichnen, dass dieses Datenmodell das Datenmodell des Benutzerprofils für eine bestimmte Seite ist, setze die Einstellung AUTH_PROFILE_MODULE auf eine Zeichenkette, die aus folgenden Teilen, durch einem Punkt getrennt, besteht:

  1. Der Name (normalisiert zu Kleinschreibung) der Applikation, in der das Benutzerprofil definiert ist (in anderen Worten, eine kleingeschriebene Version des Namen, der an manage.py startapp weitergegeben wurde, um die Anwendung zu erzeugen).
  2. Der Name (normalisiert zu Kleinschreibung) der Datenmodell-Klasse.

Wenn zum Beispiel das Benutzerprofil -Datenmodell durch die Klasse UserProfile repräsentiert wird, die in der Anwendung accounts definiert wurde, würde die dazugehörige Einstellung sein:

AUTH_PROFILE_MODULE = 'accounts.userprofile'

Wenn ein Benutzerprofil-Datenmodell auf diese Art und Weise festgelegt wurde, hat jedes User-Objekt eine Methode – get_profile() – die eine Instanz des Benutzerprofil-Datenmodell zurückgibt, das mit User verknüpft ist.

Für weitere Informationen, siehe Kapitel 12 des Django-Buches.

Authentifizierung mit Webanfragen

Bis jetzt hat sich dieses Dokument mit den Low-level-APIs zur Manipulation von authentifiezierungsabhängigen Objekten beschäftigt. Auf einer höheren Ebene kann Django dieses Authentifizierungs-Framework in sein System von Request Objekten einhaken.

Installiere zuerst die Middleware SessionMiddleware und AuthenticationMiddleware, in dem du sie zu deiner MIDDLEWARE_CLASSES-Einstellung hinzufügst. Siehe in der Session-Dokumentation für mehr Informationen.

Sobald du diese Middleware installiert hast, wirst du in den Views auf request.user zugreifen können. request.user wird dir ein User-Objekt geben, das den zur Zeit angemeldeten Benutzer repräsentiert. Wenn ein Benutzer gerade nicht angemeldet ist, wird request.user auf eine Instanz von AnonymousUser gesetzt (siehe im vorherigen Abschnitt). Du kannst sie unterscheiden mit is_authenticated(), etwa so:

if request.user.is_authenticated():
    # Mache etwas für authentifizierte Benutzer.
else:
    # Mache etwas für anonyme Benutzer.

Wie man einen Benutzer anmeldet

Django bietet zwei Funktionen in django.contrib.auth: authenticate() und login().

Um einen bestimmten Benutzername und ein Passwort zu authentifizieren, benutze authenticate(). Es nimmt zwei Parameter entgegen, username und password, und gibt ein User-Objekt zurück, wenn das Passwort für den Benutzernamen korrekt war. Wenn das Passwort falsch war, gibt authenticate() None zurück. Beispiel:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    if user.is_active:
        print "Korrekter Benutzername und Passwort!"
    else:
        print "Dein Account wurde deaktiviert!!"
else:
    print "Dein Benutzername und Passwort waren falsch."

Um einen Benutzer in einer View anzumelden, benutze login(). Es nimmt ein HttpRequest-Objekt und ein User-Objekt entgegen. login() speichert, mit Hilfe Djangos Session-Framework, die ID des Benutzers in der Session. Deswegen musst du sicherstellen, dass die Session-Middleware installiert wurde (siehe oben).

Dieses Beispiel zeigt, wie du authenticate() und login benutzen könntest:

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            # Weiterleiten auf Erfolgsseite.
        else:
            # Gibt eine 'Deaktivierter Account' Fehlermeldung aus.
    else:
        # Gibt eine 'Fehlerhafte Anmeldung' Fehlermeldung aus.

authenticate() zuerst aufrufen

Wenn du einen Benutzer manuell anmeldest, musst du authenticate() aufrufen, bevor du login() aufrufst. authenticate() setzt ein Attribut auf den User, das festlegt welches Authentifizierungs-Backend erfolgreich für den Benutzer angemeldet wurde (siehe in der Backend-Dokumentation für mehr Details). Diese Information wird später während des Anmeldevorgangs benötigt.

Ein Benutzerpasswort manuell prüfen

Wenn du einen Benutzer manuell authentifizieren willst, indem du ein Passwort in Klartext mit dem Hash-Passwort in der Datenbank vergleichst, benutze die fertige Funktion django.contrib.auth.models.check_password. Sie nimmt zwei Argumente entgegen: das Passwort in Klartext, das überprüft werden soll und den vollen Wert vom password-Feld des Benutzers in der Datenbank. Sie gibt True zurück, wenn die Passwörter übereinstimmen und False, wenn nicht.

Wie man einen Benutzer abmeldet

Um einen Benutzer, der mit django.contrib.auth.login() angemeldet wurde wieder abzumelden, benutze django.contrib.auth.logout() in deiner View. Sie nimmt ein HttpRequest-Objekt entgegen und gibt keinen Wert zurück. Beispiel:

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Weiterleiten an eine Erfolgsseite.

Beachte, dass logout() keine Fehler ausgibt, wenn der Benutzer nicht angemeldet war.

Zugriff für angemeldete Benutzer beschränken

Die rohe Methode

Die einfache, rohe Methode, den Zugriff auf Seiten zu beschränken, ist request.user.is_authenticated() zu prüfen und ansonsten auf eine Login-Seite umzuleiten:

from django.http import HttpResponseRedirect

def my_view(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/?next=%s' % request.path)
    # ...

…oder zeige eine Fehlermeldung an:

def my_view(request):
    if not request.user.is_authenticated():
        return render_to_response('myapp/login_error.html')
    # ...

Der login_required-Decorator

Zum Abkürzen kannst du den bequemen login_required Decorator benutzen:

from django.contrib.auth.decorators import login_required

def my_view(request):
    # ...
my_view = login_required(my_view)

Hier ist ein entsprechendes Beispiel, das die kompaktere, in Python 2.4 eingeführte Decorator-Syntax benutzt:

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    # ...

In der Django-Entwicklerversion, nimmt login_required auch einen optionalen redirect_field_name-Parameter. Beispiel:

from django.contrib.auth.decorators import login_required

def my_view(request):
    # ...
my_view = login_required(redirect_field_name='redirect_to')(my_view)

Hier noch ein entsprechendes Beispiel der kompakteren Decorator-Syntax, die in Python 2.4 eingeführt wurde:

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='redirect_to')
def my_view(request):
    # ...

login_required macht folgendes:

  • Wenn der Benutzer nicht angemeldet ist, leite auf settings.LOGIN_URL (standardmäßig /accounts/login/), übergib die aktuelle, absolute URL im Query-String als next oder den Wert von redirect_field_name. Zum Beispiel: /accounts/login/?next=/polls/3/.
  • Wenn der Benutzer angemeldet ist, führe die View normal aus. Der Code der View darf davon ausgehen, dass der Benutzer angemeldet ist.

Beachte, dass du die entsprechende Django-View auf settings.LOGIN_URL leiten musst. So kannst du z. B., die Standardeinstellung benutzend, die folgende Ziele in deine URLconf eintragen:

(r'^accounts/login/$', 'django.contrib.auth.views.login'),

Das macht django.contrib.auth.views.login:

  • Wenn über GET aufgerufen, zeigt sie ein Anmeldeformular, das einen POST auf die gleiche URL schickt. Mehr dazu gleich.
  • Wenn über POST aufgerufen, versucht sie den Benutzer anzumelden. Ist die Anmeldung erfolgreich, leitet die View auf die URL, die in next festgelegt ist. Ist next nicht bereitgestellt, leitet sie auf settings.LOGIN_REDIRECT_URL (diese ist standardmäßig /accounts/profile/). Ist die Anmeldung nicht erfolgreich, wird das Anmeldeformular wieder angezeigt.

Es ist deine Aufgabe das Anmeldeformular standardmäßig in einem Template registration/login.html bereitzustellen. Dieses Template bekommt drei Template-Kontext-Variablen:

  • form: Ein FormWrapper-Objekt, das das Anmeldeformular repräsentiert. Siehe in der Formular-Dokumentation``_ für mehr über ``FormWrapper-Objekte.
  • next: Die URL, zu der nach erfolgreicher Anmeldung weitergeleitet werden soll. Dies kann auch einen Query-String enthalten.
  • site_name: Der Name der aktuellen Site, übereinstimmend mit der SITE_ID-Einstellung. Wenn du die Django-Entwicklerversion benutzt und nicht das Site-Framework installiert hast, ist dieser Wert auf request.META['SERVER_NAME'] gesetzt. Für mehr über Sites, siehe die Site-Framework-Dokumentation.

Wenn du es vorziehst, nicht das Template registration/login.html aufzurufen, kannst du den template_name-Parameter in deiner URLconf über zusätzliche Argumente an die View weitergeben. Das folgende Beispiel in der URL-Konfiguration würde z. B. dafür sorgen, das myapp/login.html benutzt wird:

(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),

Hier ist ein Beispiel-Template für registration/login.html, das du als Ansatzpunkt benutzen kannst. Es setzt voraus, dass du ein base.html-Template hast, in dem ein content-Block definiert wurde:

{% extends "base.html" %}

{% block content %}

{% if form.has_errors %}
<p>Dein Benutzername und Passwort stimmen nicht. Versuche es noch einmal.</p>
{% endif %}

<form method="post" action=".">
<table>
<tr><td><label for="id_username">Benutzername:</label></td><td>{{ form.username }}</td></tr>
<tr><td><label for="id_password">Passwort:</label></td><td>{{ form.password }}</td></tr>
</table>

<input type="submit" value="Anmelden" />
<input type="hidden" name="next" value="{{ next }}" />
</form>

{% endblock %}

Andere eingebaute Views

Zusätzlich zur login-View enthält das Authentifizierungssystem ein paar andere nützliche eingebaute Views:

logout

Vollständiger Pfad zur View: django.contrib.auth.views.logout

Beschreibung:

Meldet einen Benutzer vom System ab.

Optionale Argumente:

  • template_name: Der vollständige Name eines Templates, das angezeigt werden soll, nachdem der Benutzer abgemeldet wurde. Dies ist standardmäßig registration/logged_out.html, wenn keine Argumente mitgeliefert werden.

Template-Kontext:

  • title: Der String “Logged out”, lokalisiert.

logout_then_login

Vollständiger Pfad zur View: django.contrib.auth.views.logout_then_login

Beschreibung:

Meldet einen Benutzer vom System ab und leitet auf die Anmeldeseite weiter.

Optionale Argumente:

  • login_url: Die URL der Anmeldeseite, auf die weitergeleitet wird. Dies ist standardmäßig auf settings.LOGIN_URL eingestellt, wenn keine Argumente mitgeliefert werden.

password_change

Vollständiger Pfad zur View: django.contrib.auth.views.password_change

Beschreibung:

Erlaubt einem Benutzer, sein Passwort zu ändern.

Optionale Argumente:

  • template_name: Der vollständige Name eines Templates, das benutzt werden soll, um das “Passwort ändern”-Formular anzuzeigen. Dies ist standardmäßig auf registration/password_change_form.html eingestellt, wenn keine Argumente mitgeliefert werden.

Template-Kontext:

  • form: Das “Passwort ändern”-Formular.

password_change_done

Vollständiger Pfad zur View: django.contrib.auth.views.password_change_done

Beschreibung:

Die Seite, die gezeigt wird, nachdem ein Benutzer sein Passwort geändert hat.

Optionale Argumente:

  • template_name: Der vollständige Name von einem Template, das benutzt werden soll. Dies ist standardmäßig auf registration/password_change_done.html eingestellt, wenn keine Argumente mitgeliefert werden.

password_reset

Vollständiger Pfad zur View: django.contrib.auth.views.password_reset

Beschreibung:

Erlaubt einem Benutzer, sein Passwort zurückzusetzen und sendet ihm in einer E-Mail ein neues Passwort.

Optionale Argumente:

  • template_name: Der vollständige Name eines Templates, dass benutzt werden soll, um das Formular zum Zurücksetzen des Passwortes anzuzeigen. Dies ist standardmäßig auf registration/password_reset_form.html eingestellt, wenn keine Argumente mitgeliefert werden.
  • email_template_name: Der vollständige Name eines Templates, das benutzt werden soll, um die E-Mail mit dem neuen Passwort zu generieren. Dieses ist standardmäßig auf registration/password_reset_email.html eingestellt, wenn keine Argumente mitgeliefert werden.

Template-Kontext:

  • form: Das Formular zu Zurücksetzen des Benutzerpasswortes.

password_reset_done

Vollständiger Pfad zur View: django.contrib.auth.views.password_reset_done

Beschreibung:

Die Seite, die gezeigt wird, nachdem der Benutzer sein Passwort zurückgesetzt hat.

Optionale Argumente:

  • template_name: Der vollständige Name eines Templates, das benutzt werden soll. Dies ist standardmäßig auf registration/password_reset_done.html eingestellt, wenn es nicht mitgeliefert wird.

redirect_to_login

Vollständiger Pfad zur View: django.contrib.auth.views.redirect_to_login

Beschreibung:

Leitet auf die Anmeldeseite weiter und nach erfolgreichem Anmelden zu einer anderen URL.

Erforderliche Argumente:

  • next: Die URL, zu der nach erfolgreichem Anmelden weitergeleitet werden soll.

Optionale Argumente:

  • login_url: Die URL der Anmeldeseite, auf die weitergeleitet werden soll. Dies ist standardmäßig auf settings.LOGIN_URL eingestellt, wenn es nicht mitgeliefert wird.

Eingebaute Manipulatoren

Wenn du nicht die eingebauten Views benutzen möchtest, aber dennoch den Vorteil behalten möchtest, keine Manipulatoren für diese Funktionalität schreiben zu müssen, bietet das Authentifizierungssystem verschiedene eingebaute Manipulatoren:

  • django.contrib.auth.forms.AdminPasswordChangeForm: Ein Manipulator, der im Admin-Interface benutzt wird, um das Passwort des Benutzers zu ändern.
  • django.contrib.auth.forms.AuthenticationForm: Ein Manipulator, um den Benutzer anzumelden.
  • django.contrib.auth.forms.PasswordChangeForm: Ein Manipulator, der dem Benutzer erlaubt, sein Passwort zu ändern.
  • django.contrib.auth.forms.PasswordResetForm: Ein Manipulator, um das Passwort des Benutzers zurückzusetzen und ihm ein neues Passwort per E-Mail zu schicken.
  • django.contrib.auth.forms.UserCreationForm: Ein Manipulator, zum Erstellen eines neuen Benutzers.

Zugriff für angemeldete Benutzer beschränken, die einen Test bestehen

Um den Zugriff anhand bestimmter Berechtigungen oder anderer Tests zu beschränken, würdest du im Wesentlichen das Gleiche machen, was im vorherigen Abschnitt beschrieben wurde.

Am einfachsten ist es, die Überprüfung des request.user direkt in der View durchzuführen. So prüft die folgende View z. B., ob der Benutzer angemeldet ist und die Berechtigung polls.can_vote hat:

def my_view(request):
    if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
        return HttpResponse("Du kannst für diese Abstimmung nicht wählen.")
    # ...

Zur Abkürzung kannst du den komfortablen Decorator user_passes_test benutzen:

from django.contrib.auth.decorators import user_passes_test

def my_view(request):
    # ...
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view)

Wir benutzen diesen bestimmten Test als relativ einfaches Beispiel. Dennoch kannst du den permission_required()-Decorator benutzen, wenn du nur prüfen willst, ob ein Benutzer eine bestimmte Berechtigung besitzt, wie später in diesem Dokumente beschrieben.

Hier ist das Gleiche unter Benutzung der Python 2.4-Decorator-Syntax:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.has_perm('polls.can_vote'))
def my_view(request):
    # ...

user_passes_test erfordert ein Argument: Eine ausführbare Funktion (Callable), die ein User-Objekt entgegennimmt und True zurückgibt, wenn der Benutzer die Seite ansehen darf. Beachte, dass user_passes_test nicht automatisch prüft, ob User nicht anonym ist.

user_passes_test() nimmt ein optionales login_url-Argument, mit der du die URL für deine Anmeldeseite (standardmäßig settings.LOGIN_URL) festlegen kannst.

Beispiel in Python 2.3-Syntax:

from django.contrib.auth.decorators import user_passes_test

def my_view(request):
    # ...
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view)

Beispiel in Python 2.4-Syntax:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')
def my_view(request):
    # ...

Der permission_required Decorator

Relativ häufig muss überprüft werden, ob ein Benutzer ein bestimmtes Recht hat. Für diesen Fall bietet Django ein abgekürztes Verfahren: den permission_required()-Decorator. Unter seiner Verwendung könnte das vorherige Beispiel so geschrieben werden:

from django.contrib.auth.decorators import permission_required

def my_view(request):
    # ...
my_view = permission_required('polls.can_vote')(my_view)

Beachte, dass permission_required() einen optionalen login_url-Parameter entgegennimmt. Beispiel:

from django.contrib.auth.decorators import permission_required

def my_view(request):
    # ...
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)

Wie beim login_required-Decorator, ist login_url standardmäßig auf settings.LOGIN_URL eingestellt.

Zugriff auf Generic Views beschränken

Um den Zugriff auf eine Generic View zu beschränken, musst du einen einfachen Wrapper um die View schreiben und in deiner URLconf auf den Wrapper, statt auf die Generische View, verweisen. Zum Beispiel:

from django.views.generic.date_based import object_detail

@login_required
def limited_object_detail(*args, **kwargs):
    return object_detail(*args, **kwargs)

Berechtigungen

Django kommt mit einem einfachen System für Berechtigungen. Es ermöglicht dir, bestimmten Benutzern und Gruppen Rechte zuzuweisen.

Es wird von Djangos Administrationsoberfläche benutzt, doch kannst du es auch gerne für deinen eigenen Code benutzen.

Die Django-Administrationsoberfläche benutzt Berechtigungen folgendermaßen:

  • Der Zugriff auf das “add”-Formular und das Hinzufügen von Objekten ist auf Benutzer mit der “add”-Berechtigung für diese Art von Objekt beschränkt.
  • Der Zugriff auf die Änderungsliste, das “change”-Formular und das Ändern eines Objektes ist auf Benutzer mit der “add”-Berechtigung für diese Art von Objekt beschränkt.
  • Das Löschen eines Objektes ist auf Benutzer mit der “delete”-Berechtigung für diese Art von Objekt beschränkt.

Berechtigungen werden global pro Objekttyp gesetzt, nicht für einzelne Objekt-Instanzen. Es ist zwar zum Beispiel möglich: “Mary kann News ändern”, aber zur Zeit noch nicht möglich: “Mary kann News ändern, aber nur die, die sie selber erstellt hat” oder “Mary kann nur News ändern, die einen bestimmten Status, ein Publikationsdatum oder eine ID haben”. Letzteres wird derzeit von den Django-Entwicklern diskutiert.

Standard-Berechtigungen

Drei grundlegende Berechtigungen – Hinzufügen, Ändern und Löschen – werden automatisch für jedes Django-Datenmodell erzeugt, das class Admin enthält. Im Hintergrund werden diese Berechtigungen zur auth_permission-Datenbanktabelle hinzugefügt, sobald du manage.py syncdb ausführst.

Beachte, dass die Berechtigungen nicht erzeugt werden, wenn dein Datenmodell nicht class Admin enthält. Wenn du deine Datenbank initialisierst und erst danach class Admin zu deinen Datenmodellen hinzufügst, musst du manage.py syncdb erneut ausführen. Dadurch werden alle fehlenden Berechtigungen für deine installierten Anwendungen hinzugefügt.

Eigene Berechtigungen

Um eigene Berechtigungen für ein gegebenes Datenmodell-Objekt zu erstellen, benutze das permissions-Datenmodell-Meta-Attribut.

Dieses Beispiel-Datenmodell erzeugt drei eigene Berechtigungen:

class USCitizen(models.Model):
    # ...
    class Meta:
        permissions = (
            ("can_drive", "Darf fahren"),
            ("can_vote", "Darf wählen"),
            ("can_drink", "Darf Alkohol trinken"),
        )

Dadurch werden einfach diese extra Berechtigungen erzeugt, sobald du syncdb ausführst.

API-Referenz

Genau wie Benutzer sind Berechtigungen in einem Django-Datenmodell implementiert, das in django/contrib/auth/models.py zu finden ist.

Felder

Permission-Objekte haben die folgenden Felder:

  • name – Erforderlich. 50 Zeichen oder weniger. Beispiel: 'Darf wählen'.
  • content_type – Erforderlich. Eine Referenz zur django_content_type Datenbanktabelle, die einen Eintrag für jedes installierte Django-Datenmodell enthält.
  • codename – Erforderlich. 100 Zeichen oder weniger. Beispiel: 'darf_waehlen'.

Methoden

Permission-Objekte haben die standardmäßigen API-Methoden wie jedes andere Django-Datenmodell.

Authentifizierungsdaten in Templates

Der zur Zeit angemeldete Benutzer und seine/ihre Berechtigungen werden im Template-Kontext verfügbar gemacht, wenn du RequestContext benutzt.

Formsache

Technisch gesehen werden diese Variablen im Template-Kontext nur zur Verfügung gestellt, wenn du RequestContext benutzt und deine TEMPLATE_CONTEXT_PROCESSORS-Einstellungen "django.core.context_processors.auth" enthält, was die Standardeinstellung ist. Für weitere Informationen, siehe in der RequestContext-Dokumentation.

Benutzer

Der zur Zeit angemeldete Benutzer, entweder eine User-Instanz oder eine AnonymousUser-Instanz, wird in der Template-Variable {{ user }} abgelegt:

{% if user.is_authenticated %}
    <p>Willkommen, {{ user.username }}. Vielen Dank für die Anmeldung.</p>
{% else %}
    <p>Willkommen, neuer Benutzer. Bitte melde dich an.</p>
{% endif %}

Berechtigungen

Die Berechtigungen des zur Zeit angemeldeten Benutzers werden in der Template-Variable {{ perms}} abgelegt. Dies ist eine Instanz von django.core.context_processors.PermWrapper, der einen templatefreundlichen Zugriff auf die Berechtigungen ermöglicht.

Beim {{ perms }}-Objekt ruft eine einzelne Attribut-Abfrage im Hintergrund User.has_module_perms auf. Dieses Beispiel würde True anzeigen, wenn der angemeldete Benutzer irgendwelche Rechte auf die foo-Anwendung hätte:

{{ perms.foo }}

Eine Attribut-Abfrage auf zwei Ebenen ruft im Hintergrund User.has_perm auf. Dieses Beispiel würde True anzeigen, wenn der angemeldete Benutzer irgendwelche Rechte auf foo.can_vote hätte:

{{ perms.foo.can_vote }}

Daher kannst du die Berechtigungen im Template mit {% if %}-Statements abfragen:

{% if perms.foo %}
    <p>Du hast die Rechte, etwas in der Anwendung zu machen.</p>
    {% if perms.foo.can_vote %}
        <p>Du darfst wählen!</p>
    {% endif %}
    {% if perms.foo.can_drive %}
        <p>Du darfst fahren!</p>
    {% endif %}
{% else %}
    <p>Du hast keine Berechtigungen, irgendetwas in der Anwendung zu machen.</p>
{% endif %}

Gruppen

Mit Gruppen können Benutzer allgemein kategorisiert und Berechtigungen oder andere Markierungen zugewiesen werden. Ein Benutzer kann zu einer beliebigen Anzahl von Gruppen gehören.

Ein Benutzer einer Gruppen hat automatisch die Berechtigungen der Gruppe. Wenn z. B. die Gruppe Seitenredakteure die Berechtigung can_edit_home_page hat, wird auch jeder Benutzer dieser Gruppe die Berechtigung haben.

Darüberhinaus sind Gruppen eine bequeme Möglichkeit, Benutzer zu kategorisieren, um Ihnen eine Markierung zuzuweisen oder erweiterte Funktionalität zu vergeben. So könntest du z. B. eine Gruppe Spezielle Benutzer erstellen und dann Code schreiben, der ihnen Zugriff auf einen Mitgliedsbereich der Seite gibt oder Ihnen spezielle Mitglieder-E-Mails schicken.

Mitteilungen

Das Mitteilungssystem bietet eine einfache Möglichkeit Nachrichten für bestimmte Benutzer zu sammeln.

Eine Mitteilung ist einem User zugeordnet. Es gibt kein Konzept für Ablaufdatum oder Zeitstempel.

Mitteilungen werden von der Django-Administrationsoberfläche im Anschluss an eine erfolgreiche Aktion benutzt. Zum Beispiel ist "Die Umfrage Foo wurde erfolgreich erstellt." eine Mitteilung.

Die API ist einfach:

  • Um eine neue Mitteilung zu erstellen, benutze user_obj.message_set.create(message_set='mitteilung_text').
  • Um Mitteilungen abzufragen/zu löschen, benutze` user_obj.get_and_delete_messages(), das eine Liste von Message-Objekten aus der Warteliste des Benutzers zurückgibt (wenn vorhanden) und sie dann aus der Warteliste entfernt.

In dieser Beispiel-View speichert das System eine Nachricht für den Benutzer, nachdem es eine Playlist erzeugt hat:

def create_playlist(request, songs):
    # Erzeuge eine Playlist mit bestimmten Songs.
    # ...
    request.user.message_set.create(message="Deine Playlist wurde erfolgreich hinzugefügt.")
    return render_to_response("playlists/create.html",
        context_instance=RequestContext(request))

Wenn du RequestContext benutzt, werden die Nachrichten des derzeit angemeldeten Benutzers und der Benutzer im Template-Kontext in der Variable {{ messages }} verfügbar gemacht. Hier ist ein Codebeispiel eines Templates, das Mitteilungen darstellt:

{% if messages %}
<ul>
    {% for message in messages %}
    <li>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

Beachte, dass RequestContext im Hintergrund get_and_delete_messages aufruft, weshalb alle Nachrichten gelöscht werden, selbst wenn du sie nicht anzeigst.

Abschließend ist noch anzumerken, dass dieses Mitteilungs-Framework nur mit Benutzern in der Datenbank funktioniert. Um Mitteilungen an anonyme Benutzer zu schicken, benutze das Session-Framework.

Andere Quellen für Authentifizierung

Die Authentifizierung, die mit Django geliefert wird, ist für die meisten Fälle ausreichend. Vielleicht musst du dich aber auch mit einer anderen Authentifizierungsquelle verbinden — also eine andere Quelle für Benutzernamen und Passwörter oder Authentifizierungsmethoden.

Möglicherweise hat deine Firma bereits eine LDAP-Installation, die Benutzername und Passwort jedes Mitarbeiters speichert. Sowohl für den Netzwerk-Administrator, als auch für die Benutzer würden verschiedene Zugänge in LDAP und Django-Anwendung Schwierigkeiten bedeuten.

Um mit solchen Situationen klar zu kommen, bietet das Djangos Authentifizierungssystem die Möglichkeit, andere Quellen für die Authentifizierung zu benutzen. Du kannst das standardmäßige Datenbankschema außer Kraft setzen oder es mit anderen Systemen hintereinander benutzen.

Authentifizierungs-Backends festlegen

Im Hintergrund führt Django eine Liste mit “Authentifizierungs-Backends”, die es während der Authentifizierung benutzt. Wenn – wie in “Wie man einen Benutzer abmeldet” oben beschrieben – django.contrib.auth.authenticate() aufgerufen wird, versucht Django alle Authentifizierungs-Backends zu benutzen. Wenn also die erste Authentifizierungs-Methode fehlschlägt, versucht Django die zweite (und so weiter), solange bis alle ausprobiert wurden.

Die Liste der zu benutzenden Authentifizierungs-Backends wird in den AUTHENTICATION_BACKENDS-Einstellungen näher definiert. Dies sollte ein Tuple von Python-Pfaden sein, die auf Python-Klassen zeigen, die wissen, wie authentifiziert wird. Diese Klassen können irgendwo auf dem Python-Pfad liegen.

Standardmäßig ist AUTHENTICATION_BACKENDS eingestellt auf:

('django.contrib.auth.backends.ModelBackend',)

Dieses grundlegende Authentifizierungs-Schema benutzt die Benutzerdatenbank von Django.

Die Reihenfolge der AUTHENTICATION_BACKENDS ist wichtig, wenn also der gleiche Benutzername und das gleiche Password in verschiedenen Backends vorhanden ist, hört Django mit der Überprüfung beim ersten positiven Treffer auf.

Ein Authentifizierungs-Backend schreiben

Eine Authentifizierungs-Backend ist eine Klasse, die zwei Methoden implementiert: get_user(user_id) und authenticate(**credentials).

Die get_user-Methode nimmt ein user_id entgegen – was ein Benutzername, eine Datenbank-ID oder was auch immer sein kann – und gibt ein User-Objekt zurück.

Die authenticate-Methode nimmt Berechtigungen als Schlagwort-Argumente entgegen. Normalerweise sieht das so aus:

class MyBackend:
    def authenticate(self, username=None, password=None):
        # Prüfe Benutzername/Passwort und gibt einen User zurück.

Aber es könnte auch als Token authentifizieren, etwa so:

class MyBackend:
    def authenticate(self, token=None):
        # Prüfe den Token und gibt einen User zurück.

So oder so, authenticate sollte die übergebenen Anmeldedaten überprüfen und ein User-Objekt zurückgeben, das mit den Berechtigungen übereinstimmt, wenn sie korrekt sind. Wenn sie nicht korrekt sind, sollte es None zurückgeben.

Die Django-Administrationsoberfläche ist eng mit dem Django-User-Objekt gekoppelt, das wir am Anfang dieses Dokumentes beschrieben haben. Der beste Weg damit umzugehen, ist im Moment, ein Django-User-Objekt für jeden Benutzer zu erzeugen, der in deinem Backend existiert (z. B. in deinem LDAP-Verzeichnis, deiner externen SQL-Datenbank, usw.). Du kannst entweder ein Skript schreiben, um dies im Voraus zu machen, oder deine authenticate-Methode erledigt es, wenn sich ein Benutzer das erste Mal anmeldet.

Hier ist ein Beispiel-Backend, das die Variablen username und password, die in deiner settings.py-Datei definiert sind, für die Authentifizierung benutzt. Es erzeugt ein Django-User-Objekt, wenn sich ein Benutzer das erste Mal authentifiziert:

from django.conf import settings
from django.contrib.auth.models import User, check_password

class SettingsBackend:
    """
    Authentifizierung mit den Einstellungen ADMIN_LOGIN und ADMIN_PASSWORD.

    Benutze den Anmeldenamen und einen Hash des Passworts. Zum Beispiel:

    ADMIN_LOGIN = 'admin'
    ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
    """
    def authenticate(self, username=None, password=None):
        login_valid = (settings.ADMIN_LOGIN == username)
        pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
        if login_valid and pwd_valid:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                # Erzeuge einen neuen Benutzer. Beachte, dass wir das
                # Passwort beliebig vergeben können, weil es nicht
                # geprüft wird; das Passwort aus settings.py wird hingegen
                # geprüft.
                user = User(username=username, password='get from settings.py')
                user.is_staff = True
                user.is_superuser = True
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

Autorisierung an benutzerdefinierten Backends

Benutzerdefinierte Authentifizierungs-Backends stellen ihre eigenen Berechtigungen bereit.

Das User-Datenmodell überträgt Funktionen zur Abfrage von Berechtigungen (get_group_permissions(), get_all_permissions(), has_perm() und has_module_perms()) an jedes Authentifizierungs-Backend, das diese Funktionen implementiert.

Die Berechtigungen, die ein Benutzer erhält, sind alle Berechtigungen, die von allen Backends zurückgegeben wurden. Das bedeutet, Django erteilt alle Berechtigungen, die irgendeines der Backends erteilt.

Das einfache Backend oben, könnte Berechtigungen für das magische Admin relativ einfach implementieren:

class SettingsBackend:

    # ...

    def has_perm(self, user_obj, perm):
        if user_obj.username == settings.ADMIN_LOGIN:
            return True
        else:
            return False

Dies erteilt dem Benutzer im Beispiel oben volle Berechtigungen. Beachte, dass die Backend-Authentifizierungsfunktionen alle ein User-Objekt als Argument entgegennehmen, und sie akzeptieren auch die gleichen Argumente die an die zugehörigen User-Funktionen gegeben werden.

Eine vollständige Implementierung der Autorisierung findest du in django/contrib/auth/backends.py, das das standardmäßige Backend ist und hauptsächlich die auth_permission-Tabelle abfragt.