Django 休息框架中无效令牌身份验证的自定义响应

Custom response for invalid token authentication in Django rest framework

对于下面的代码,我想 return 一个布尔值,对应于用户是否已通过身份验证。

class UserAuthenticatedView(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (AllowAny,)
    def get(self, request, format=None):
        is_authenticated = request.user.is_authenticated()
        resp = {'is_authenticated': is_authenticated}
        return Response(resp, content_type="application/json", status=status.HTTP_200_OK)

但是,对于无效令牌,控件甚至没有进入 get 方法,因此我无法自定义响应。在这种情况下,我得到的回应是:{'detail': 'invalid token'}, 知道如何自定义无效令牌的响应吗?

您可以创建 CustomTokenAuthentication class 并将 authenticate_credentials() 方法覆盖为 return 自定义响应以防令牌无效。

class CustomTokenAuthentication(TokenAuthentication):

    def authenticate_credentials(self, key):
        try:
            token = self.model.objects.select_related('user').get(key=key)
        except self.model.DoesNotExist:
            # modify the original exception response
            raise exceptions.AuthenticationFailed('Custom error message') 

        if not token.user.is_active:
            # can also modify this exception message
            raise exceptions.AuthenticationFailed('User inactive or deleted')

        return (token.user, token)

执行此操作后,在您的 DRF 设置中或在 per-view/viewset 基础上定义此自定义令牌身份验证 class。

另一种选择是创建 custom exception handler. In that, you can check if the exception raised was of type AuthenticationFailed and the exception message is 'invalid token'. There you can modify the exception message (also check this official DRF example)。

这对我有用:

自定义身份验证class:

class MyAuthentication(authentication.TokenAuthentication):
    def authenticate_credentials(self, key):
        try:
            token = self.model.objects.select_related('user').get(key=key)
        except self.model.DoesNotExist:
            return (None, '')

        if not token.user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

        return (token.user, token)

查看class:

class UserAuthenticatedView(APIView):
    authentication_classes = (MyAuthentication,)
    permission_classes = (AllowAny,)

    def get(self, request, format=None):
        is_authenticated = False
        if request.user and request.user.is_authenticated():
            is_authenticated = True
        resp = {'is_authenticated': is_authenticated}
        return Response(resp, content_type="application/json", status=status.HTTP_200_OK)