Django Rest Framework Token-Authentifizierung

78

Ich habe die Django Rest Framework Guides gelesen und alle Tutorials durchgeführt. Alles schien Sinn zu machen und so zu funktionieren, wie es sollte. Ich habe die Basis- und Sitzungsauthentifizierung wie beschrieben ausgeführt. http://django-rest-framework.org/api-guide

Ich habe jedoch Probleme mit dem Teil der Token-Authentifizierung in der Dokumentation, der etwas fehlt oder nicht so ausführlich ist wie die Tutorials.
http://django-rest-framework.org/api-guide/authentication/#tokenauthentication

Es heißt, ich muss Token für Benutzer erstellen, gibt aber an, wo in models.py?

Meine Frage ist:

Kann jemand den Token-Authentifizierungsteil der Dokumentation für einen ersten Timer etwas besser erklären?

Prometheus
quelle

Antworten:

71

Nein, nicht in Ihrer models.py - auf der Modellseite müssen Sie lediglich die entsprechende App ( rest_framework.authtoken) in Ihre einbinden INSTALLED_APPS. Dadurch wird ein Token-Modell bereitgestellt, das für den Benutzer mit einem Fremdschlüssel versehen ist.

Sie müssen lediglich entscheiden, wann und wie diese Token-Objekte erstellt werden sollen. Bekommt jeder Benutzer in Ihrer App automatisch ein Token? Oder nur bestimmte autorisierte Benutzer? Oder nur wenn sie speziell eine anfordern?

Wenn jeder Benutzer immer ein Token haben sollte, befindet sich auf der von Ihnen verknüpften Seite ein Codeausschnitt, der Ihnen zeigt, wie Sie ein Signal einrichten, um sie automatisch zu erstellen:

@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

(setzen diese in einer Datei models.py, überall, und es wird registriert, wenn ein Django - Thread startet)

Wenn Token nur zu bestimmten Zeiten erstellt werden sollen, müssen Sie das Token in Ihrem Ansichtscode zum richtigen Zeitpunkt erstellen und speichern:

# View Pseudocode
from rest_framework.authtoken.models import Token

def token_request(request):
    if user_requested_token() and token_request_is_warranted():
        new_token = Token.objects.create(user=request.user)

Sobald das Token erstellt (und gespeichert) wurde, kann es zur Authentifizierung verwendet werden.

Ian Clelland
quelle
Was bedeutet das post_save ?
244boy
2
@ 244boy Es wird create_auth_tokenals Signalhandler eingerichtet, sodass jedes Mal , wenn a Usergespeichert wird (daher post_save), create_auth_tokenaufgerufen wird. Signale sind der interne Mechanismus zur Behandlung von Lebenszyklusereignissen von django.
Jim K.
86

@ ian-clelland hat bereits die richtige Antwort gegeben. Es gibt nur ein paar winzige Teile, die in seinem Beitrag nicht erwähnt wurden, daher werde ich die vollständigen Verfahren dokumentieren (ich verwende Django 1.8.5 und DRF 3.2.4):

  1. Führen Sie die folgenden Schritte aus, bevor Sie den Superuser erstellen. Andernfalls wird dem Superuser sein Token nicht erstellt.

  2. Gehen Sie zu settings.py und fügen Sie Folgendes hinzu:

    INSTALLED_APPS = (
        'rest_framework',
        'rest_framework.authtoken',
        'myapp',
    )
    
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
        )
    }
    
  3. Fügen Sie den folgenden Code in myapp ‚s models.py :

    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from rest_framework.authtoken.models import Token
    from django.conf import settings
    
    # This code is triggered whenever a new user has been created and saved to the database
    @receiver(post_save, sender=settings.AUTH_USER_MODEL)
    def create_auth_token(sender, instance=None, created=False, **kwargs):
        if created:
            Token.objects.create(user=instance)
    

    Wenn Sie expliziter sein möchten, erstellen Sie alternativ eine Datei mit dem Namen signal.py unter myapp project. Geben Sie den obigen Code ein und schreiben Sie in __init__.pyimport signals

  4. Öffnen Sie ein Konsolenfenster, navigieren Sie zu Ihrem Projektverzeichnis und geben Sie den folgenden Befehl ein:

    python manage.py migrate
    python manage.py makemigrations
    

    Schauen Sie in Ihre Datenbank, eine Tabelle mit dem Namen authtoken_token sollte mit den folgenden Feldern erstellt werden: Schlüssel (dies ist der Token-Wert), erstellt (das Datum, zu dem sie erstellt wurde), Benutzer-ID (ein Fremdschlüssel, der auf die ID-Spalte der Tabelle auth_user verweist)

  5. Erstellen Sie einen Superuser mit python manage.py createsuperuser. Schauen Sie sich nun die Tabelle authtoken_token in Ihrer Datenbank an select * from authtoken_token;. Sie sollten sehen, dass ein neuer Eintrag hinzugefügt wurde.

  6. Mit curloder einer viel einfacheren Alternative httpie , um den Zugriff auf Ihre API zu testen, verwende ich httpie:

    http GET 127.0.0.1:8000/whatever 'Authorization: Token your_token_value'
    

    Das ist es. Von nun an müssen Sie für jeden API-Zugriff den folgenden Wert in den HTTP-Header aufnehmen ( achten Sie auf die Leerzeichen ):

    Authorization: Token your_token_value
    
  7. (Optional) DRF bietet auch die Möglichkeit, das Token eines Benutzers zurückzugeben, wenn Sie den Benutzernamen und das Kennwort angeben. Alles was Sie tun müssen, ist Folgendes in urls.py aufzunehmen :

    from rest_framework.authtoken import views
    
    urlpatterns = [
        ...
        url(r'^api-token-auth/', views.obtain_auth_token),
    ]
    

    Verwenden von httpie zur Überprüfung:

    http POST 127.0.0.1:8000/api-token-auth/ username='admin' password='whatever'
    

    Im Rückgabekörper sollten Sie Folgendes sehen:

    {
        "token": "blah_blah_blah"
    }
    

Das ist es!

Cheng
quelle
Danke für den ausführlichen Kommentar. Wo wird der Token abgeglichen? Können wir etwas bearbeiten?
Vidya
1
@rrmo Die Token werden in einer Datenbanktabelle mit dem Namen auth_token gespeichert (oder ähnlichem, ich kann mich nicht an den genauen Namen erinnern. Die Tabelle enthält nur drei Spalten, Primärschlüssel, Token und einen Fremdschlüssel für das Benutzermodell). Jedes Mal, wenn eine Authentifizierungsanforderung empfangen wird, wird die Datenbanktabelle abgerufen, um das eingehende Token mit den gespeicherten zu vergleichen.
Cheng
@Cheng Zu Punkt 3: Setzen Code in signals.py und das Hinzufügen import signalsin __init__.pyRaises django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yetin Django 1.9.
Narendra-Choudhary
Aber wie erhalten Sie das Token, zum Beispiel von einer mobilen App, generieren Sie das Token mit Benutzername und Passwort (zum Beispiel erstellen Sie ein Base64-Token) und senden es in der Anfrage?
Jesus Almaral - Hackaprende
@JesusAlmaral Das Token wird auf der Serverseite und nicht auf der Clientseite erstellt. Nachdem der Benutzer die Registrierungsinformationen ausgefüllt und an den Server gesendet hat, um ein Konto zu erstellen, wird zusammen mit dem Konto ein Token erstellt. Sobald das Token erstellt wurde, können Sie seinen Wert an die Clientseite senden.
Cheng
18

Unter Django 1.8.2 und Rest Framework 3.3.2 reichte es nicht aus, alle oben genannten Punkte zu befolgen, um eine tokenbasierte Authentifizierung zu ermöglichen.

Obwohl die Einstellung REST_FRAMEWORK in der Django-Einstellungsdatei angegeben ist, sind funktionsbasierte Ansichten erforderlich. @APi_view decorator:

from rest_framework.decorators import api_view

@api_view(['POST','GET'])
def my_view(request):
    if request.user.is_authenticated():
       ...

Andernfalls wird überhaupt keine Tokenauthentifizierung durchgeführt

Super S.
quelle
2
Trotz der wenigen positiven Stimmen fügt diese Antwort einen sehr nützlichen Punkt hinzu: Ohne den @ api_view-Dekorator verwenden die Ansichten nicht die Tokenauthentifizierung. Vielleicht könnte es der gewählten Antwort hinzugefügt werden.
Paolo Stefan
Zweieinhalb Jahre später ... DANKE
zobbo
14

Um meine zwei Cent hinzuzufügen, können Sie diese Aufgabe auch folgendermaßen ausführen, wenn Sie einen benutzerdefinierten Benutzermanager haben, der die Benutzererstellung (und -aktivierung) übernimmt.

from rest_framework.authtoken.models import Token
# Other imports

class UserManager(BaseUserManager):

    def create_user(self, **kwargs):
        """
        This is your custom method for creating user instances. 
        IMHO, if you're going to do this, you might as well use a signal.

        """
        # user = self.model(**kwargs) ...
        Token.objects.create(user=user)

    #You may also choose to handle this upon user activation. 
    #Again, a signal works as well here.

    def activate_user(**kwargs):
        # user = ...
        Token.objects.create(user=user)

Wenn Sie bereits Benutzer erstellt haben, können Sie in die Python-Shell Ihres Terminals wechseln und Tokens für alle Benutzer in Ihrer Datenbank erstellen.

>>> from django.contrib.auth.models import User
>>> from rest_framework.authtoken.models import Token 
>>> for user in User.objects.all():
>>> ...    Token.objects.create(user=user)

Hoffentlich hilft das.

parsenz
quelle
10

Es gibt eine sauberere Möglichkeit, das Benutzertoken abzurufen.

Führen Sie einfach die shell.py-Shell aus

und dann

from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
u = User.objects.get(username='admin')
token = Token.objects.create(user=u)
print token.key

dann sollte ein Datensatz in der Tabelle DB_Schema.authtoken_token gefunden werden

Jeremy Kankai Zhang
quelle
6

Zusätzlich zu den hervorragenden Antworten möchte ich einen besseren Ansatz für die Tokenauthentifizierung erwähnen: JSON Web Token Authentication. Die von http://getblimp.github.io/django-rest-framework-jwt/ angebotene Implementierung ist sehr einfach zu verwenden.

Die Vorteile werden in dieser Antwort näher erläutert .

Def_Os
quelle