一尘不染

RESTful API的令牌身份验证:令牌是否应该定期更改?

django

我正在使用Django和django-rest-framework构建RESTful API 。

作为身份验证机制,我们选择了“令牌身份验证”,而我已经按照Django-REST-Framework的文档实施了它,问题是,应用程序应该定期更新/更改令牌吗?是应该续签令牌的移动应用程序,还是应该由网络应用程序自主执行?

最佳做法是什么?

有人在Django REST Framework方面经验丰富,可以提出技术解决方案吗?

(最后一个问题的优先级较低)


阅读 539

收藏
2020-03-31

共1个答案

一尘不染

最好让移动客户端定期更新其身份验证令牌。这当然要由服务器来实施。

默认的TokenAuthentication类不支持此功能,但是你可以对其进行扩展以实现此功能。

例如:

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

还需要覆盖默认的rest框架登录视图,以便在登录完成后刷新令牌:

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()

并且不要忘记修改网址:

urlpatterns += patterns(
    '',
    url(r'^users/login/?$', '<path_to_file>.obtain_expiring_auth_token'),
)
2020-03-31