Il est recommandé que les clients mobiles renouvellent périodiquement leur jeton d'authentification. C'est bien sûr au serveur de faire respecter.
La classe TokenAuthentication par défaut ne prend pas en charge cela, mais vous pouvez l'étendre pour obtenir cette fonctionnalité.
Par exemple:
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
Il est également nécessaire de remplacer la vue de connexion par défaut du cadre de repos, afin que le jeton soit actualisé chaque fois qu'une connexion est effectuée:
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()
Et n'oubliez pas de modifier les URL:
urlpatterns += patterns(
'',
url(r'^users/login/?$', '<path_to_file>.obtain_expiring_auth_token'),
)
Si quelqu'un est intéressé par cette solution mais souhaite avoir un jeton valide pendant un certain temps, il est alors remplacé par un nouveau jeton, voici la solution complète (Django 1.6):
yourmodule / views.py:
yourmodule / urls.py:
votre projet urls.py (dans le tableau urlpatterns):
yourmodule / authentication.py:
Dans vos paramètres REST_FRAMEWORK, ajoutez ExpiringTokenAuthentication en tant que classe d'authentification au lieu de TokenAuthentication:
la source
'ObtainExpiringAuthToken' object has no attribute 'serializer_class'
lorsque j'essaye d'accéder au point de terminaison de l'API. Je ne sais pas ce qui me manque.J'ai essayé la réponse @odedfos mais j'ai eu une erreur trompeuse . Voici la même réponse, fixe et avec des importations appropriées.
views.py
authentication.py
la source
Je pensais que je donnerais une réponse Django 2.0 en utilisant DRY. Quelqu'un a déjà construit cela pour nous, google Django OAuth ToolKit. Disponible avec pépin,
pip install django-oauth-toolkit
. Instructions sur l'ajout du token ViewSets avec des routeurs: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html . C'est similaire au tutoriel officiel.Donc, fondamentalement, OAuth1.0 était plus la sécurité d'hier qui est ce qu'est TokenAuthentication. Pour obtenir des jetons d'expiration sophistiqués, OAuth2.0 fait fureur de nos jours. Vous obtenez un AccessToken, RefreshToken et une variable de portée pour affiner les autorisations. Vous vous retrouvez avec des crédits comme celui-ci:
la source
L'auteur a demandé
Mais toutes les réponses écrivent sur la façon de changer automatiquement le jeton.
Je pense que le changement de jeton périodiquement par jeton n'a pas de sens. Le cadre de repos crée un jeton qui a 40 caractères, si l'attaquant teste 1000 jetons toutes les secondes, il faut des
16**40/1000/3600/24/365=4.6*10^7
années pour obtenir le jeton. Vous ne devez pas vous inquiéter que l'attaquant teste votre jeton un par un. Même si vous avez changé votre jeton, la probabilité de deviner votre jeton est la même.Si vous craignez que les attaquants puissent peut-être obtenir votre jeton, vous le changez donc périodiquement, qu'après que l'attaquant ait obtenu le jeton, il puisse également changer votre jeton, alors l'utilisateur réel est expulsé.
Ce que vous devez vraiment faire est d'empêcher l'attaquant d'obtenir le jeton de votre utilisateur, utilisez https .
Au fait, je dis simplement que le changement de jeton par jeton n'a aucun sens, que le changement de jeton par nom d'utilisateur et mot de passe est parfois signifiant. Peut-être que le jeton est utilisé dans un environnement http (vous devez toujours éviter ce genre de situation) ou un tiers (dans ce cas, vous devez créer un type de jeton différent, utilisez oauth2) et lorsque l'utilisateur fait quelque chose de dangereux comme changer vous devez vous assurer de ne plus utiliser le jeton d'origine car il a peut-être été révélé par l'attaquant à l'aide des outils sniffer ou tcpdump.
la source
Vous pouvez utiliser http://getblimp.github.io/django-rest-framework-jwt
Cette bibliothèque est capable de générer un jeton qui a une date d'expiration
Pour comprendre la différence entre le jeton par défaut DRF et le jeton fourni par le DRF, consultez:
Comment faire évoluer l'authentification Django REST JWT avec plusieurs serveurs Web?
la source
Si vous remarquez qu'un jeton est comme un cookie de session, vous pouvez vous en tenir à la durée de vie par défaut des cookies de session dans Django: https://docs.djangoproject.com/en/1.4/ref/settings/#session-cookie-age .
Je ne sais pas si Django Rest Framework gère cela automatiquement, mais vous pouvez toujours écrire un court script qui filtre les anciens et les marque comme expirés.
la source
Je pensais juste que j'ajouterais le mien car cela m'a été utile. J'utilise généralement la méthode JWT, mais parfois quelque chose comme ça est mieux. J'ai mis à jour la réponse acceptée pour django 2.1 avec les importations appropriées.
authentication.py
views.py
la source
juste pour continuer à ajouter à la réponse @odedfos, je pense qu'il y a eu quelques changements dans la syntaxe, donc le code de ExpiringTokenAuthentication doit être ajusté:
N'oubliez pas non plus de l'ajouter à DEFAULT_AUTHENTICATION_CLASSES au lieu de rest_framework.authentication.TokenAuthentication
la source