Es wird empfohlen, dass mobile Clients ihr Authentifizierungstoken regelmäßig erneuern. Dies muss natürlich vom Server durchgesetzt werden.
Die Standard-TokenAuthentication-Klasse unterstützt dies nicht. Sie können sie jedoch erweitern, um diese Funktionalität zu erreichen.
Beispielsweise:
from rest_framework.authentication import TokenAuthentication, get_authorization_header
from rest_framework.exceptions import AuthenticationFailed
class ExpiringTokenAuthentication(TokenAuthentication):
def authenticate_credentials(self, key):
try:
token = self.model.objects.get(key=key)
except self.model.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid token')
if not token.user.is_active:
raise exceptions.AuthenticationFailed('User inactive or deleted')
# This is required for the time comparison
utc_now = datetime.utcnow()
utc_now = utc_now.replace(tzinfo=pytz.utc)
if token.created < utc_now - timedelta(hours=24):
raise exceptions.AuthenticationFailed('Token has expired')
return token.user, token
Es ist auch erforderlich, die Standard-Anmeldeansicht für das Rest-Framework zu überschreiben, damit das Token bei jeder Anmeldung aktualisiert wird:
class ObtainExpiringAuthToken(ObtainAuthToken):
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
token, created = Token.objects.get_or_create(user=serializer.validated_data['user'])
if not created:
# update the created time of the token to keep it valid
token.created = datetime.datetime.utcnow()
token.save()
return Response({'token': token.key})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
obtain_expiring_auth_token = ObtainExpiringAuthToken.as_view()
Und vergessen Sie nicht, die URLs zu ändern:
urlpatterns += patterns(
'',
url(r'^users/login/?$', '<path_to_file>.obtain_expiring_auth_token'),
)
Wenn jemand an dieser Lösung interessiert ist, aber ein Token haben möchte, das für eine bestimmte Zeit gültig ist, wird es durch ein neues Token ersetzt. Hier ist die vollständige Lösung (Django 1.6):
yourmodule / views.py:
yourmodule / urls.py:
Ihr Projekt urls.py (im Array urlpatterns):
yourmodule / authentication.py:
Fügen Sie in Ihren REST_FRAMEWORK-Einstellungen ExpiringTokenAuthentication als Authentifizierungsklasse anstelle von TokenAuthentication hinzu:
quelle
'ObtainExpiringAuthToken' object has no attribute 'serializer_class'
wenn ich versuche, auf den API-Endpunkt zuzugreifen. Ich bin mir nicht sicher, was mir fehlt.Ich habe versucht, @odedfos zu beantworten, aber ich hatte einen irreführenden Fehler . Hier ist die gleiche Antwort, fest und mit richtigen Importen.
views.py
authentication.py
quelle
Ich dachte, ich würde eine Django 2.0-Antwort mit DRY geben. Jemand hat dies bereits für uns entwickelt, Google Django OAuth ToolKit. Erhältlich mit pip ,
pip install django-oauth-toolkit
. Anweisungen zum Hinzufügen des Tokens ViewSets mit Routern: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html . Es ähnelt dem offiziellen Tutorial.Im Grunde genommen war OAuth1.0 also mehr Sicherheit von gestern, was TokenAuthentication ist. OAuth2.0 ist heutzutage der letzte Schrei, um ausgefallene Token zu erhalten. Sie erhalten eine AccessToken-, RefreshToken- und Bereichsvariable, um die Berechtigungen zu optimieren. Sie haben am Ende folgende Creds:
quelle
Der Autor fragte
In allen Antworten wird jedoch darüber geschrieben, wie das Token automatisch geändert werden kann.
Ich denke, Token regelmäßig durch Token zu ändern ist bedeutungslos. Das Rest-Framework erstellt ein Token mit 40 Zeichen. Wenn der Angreifer 1000 Token pro Sekunde testet, dauert es
16**40/1000/3600/24/365=4.6*10^7
Jahre, bis das Token abgerufen wird. Sie sollten sich keine Sorgen machen, dass der Angreifer Ihren Token einzeln testet. Selbst wenn Sie Ihren Token geändert haben, ist die Wahrscheinlichkeit, dass Sie Ihren Token erraten, gleich.Wenn Sie befürchten, dass die Angreifer Ihnen möglicherweise einen Token erhalten, ändern Sie ihn regelmäßig. Nachdem der Angreifer den Token erhalten hat, kann er Sie auch ändern, bevor der echte Benutzer rausgeschmissen wird.
Was Sie wirklich tun sollten, ist zu verhindern, dass der Angreifer das Token Ihres Benutzers erhält. Verwenden Sie https .
Übrigens sage ich nur, dass das Ändern von Token für Token bedeutungslos ist. Das Ändern von Token für Benutzername und Passwort ist manchmal sinnvoll. Möglicherweise wird das Token in einer http-Umgebung (Sie sollten diese Situation immer vermeiden) oder in einem Drittanbieter (in diesem Fall sollten Sie eine andere Art von Token erstellen, oauth2 verwenden) verwendet, und wenn der Benutzer gefährliche Aktionen wie Änderungen ausführt Wenn Sie ein Postfach binden oder ein Konto löschen, sollten Sie sicherstellen, dass Sie das Ursprungs-Token nicht mehr verwenden, da es möglicherweise vom Angreifer mithilfe von Sniffer- oder TCPDump-Tools aufgedeckt wurde.
quelle
Sie können http://getblimp.github.io/django-rest-framework-jwt nutzen
Diese Bibliothek kann Token mit einem Ablaufdatum generieren
Um den Unterschied zwischen dem DRF-Standardtoken und dem vom DRF bereitgestellten Token zu verstehen, werfen Sie einen Blick auf:
Wie kann ich die Django REST JWT-Authentifizierungsskala mit mehreren Webservern skalieren?
quelle
Wenn Sie feststellen, dass ein Token wie ein Sitzungscookie ist, können Sie sich an die Standardlebensdauer von Sitzungscookies in Django halten: https://docs.djangoproject.com/de/1.4/ref/settings/#session-cookie-age .
Ich weiß nicht, ob Django Rest Framework dies automatisch erledigt, aber Sie können jederzeit ein kurzes Skript schreiben, das die veralteten herausfiltert und sie als abgelaufen markiert.
quelle
Ich dachte nur, ich würde meine hinzufügen, da dies für mich hilfreich war. Normalerweise gehe ich mit der JWT-Methode, aber manchmal ist so etwas besser. Ich habe die akzeptierte Antwort für Django 2.1 mit den richtigen Importen aktualisiert.
authentication.py
views.py
quelle
Ich denke, es wurden einige Änderungen an der Syntax vorgenommen, sodass der Code von ExpiringTokenAuthentication angepasst werden muss, um die Antwort von @odedfos weiter zu ergänzen:
Vergessen Sie auch nicht, es zu DEFAULT_AUTHENTICATION_CLASSES anstelle von rest_framework.authentication.TokenAuthentication hinzuzufügen
quelle