Token Authentication for RESTful API: should the token be periodically changed?

后端 未结 10 1324
庸人自扰
庸人自扰 2020-12-02 03:20

I\'m building a RESTful API with Django and django-rest-framework.

As authentication mechanism we have chosen \"Token Authentication\" and I have already implemented

10条回答
  •  囚心锁ツ
    2020-12-02 04:07

    If someone is interested by that solution but wants to have a token that is valid for a certain time then gets replaced by a new token here's the complete solution (Django 1.6):

    yourmodule/views.py:

    import datetime
    from django.utils.timezone import utc
    from rest_framework.authtoken.views import ObtainAuthToken
    from rest_framework.authtoken.models import Token
    from django.http import HttpResponse
    import json
    
    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.object['user'])
    
                utc_now = datetime.datetime.utcnow()    
                if not created and token.created < utc_now - datetime.timedelta(hours=24):
                    token.delete()
                    token = Token.objects.create(user=serializer.object['user'])
                    token.created = datetime.datetime.utcnow()
                    token.save()
    
                #return Response({'token': token.key})
                response_data = {'token': token.key}
                return HttpResponse(json.dumps(response_data), content_type="application/json")
    
            return HttpResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    obtain_expiring_auth_token = ObtainExpiringAuthToken.as_view()
    

    yourmodule/urls.py:

    from django.conf.urls import patterns, include, url
    from weights import views
    
    urlpatterns = patterns('',
        url(r'^token/', 'yourmodule.views.obtain_expiring_auth_token')
    )
    

    your project urls.py (in the urlpatterns array):

    url(r'^', include('yourmodule.urls')),
    

    yourmodule/authentication.py:

    import datetime
    from django.utils.timezone import utc
    from rest_framework.authentication import TokenAuthentication
    from rest_framework import exceptions
    
    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')
    
            utc_now = datetime.datetime.utcnow()
    
            if token.created < utc_now - datetime.timedelta(hours=24):
                raise exceptions.AuthenticationFailed('Token has expired')
    
            return (token.user, token)
    

    In your REST_FRAMEWORK settings add ExpiringTokenAuthentication as an Authentification class instead of TokenAuthentication:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',
            #'rest_framework.authentication.TokenAuthentication',
            'yourmodule.authentication.ExpiringTokenAuthentication',
        ),
    }
    

提交回复
热议问题