当 Django Rest Framework 中缺少 Auth Token 时如何返回 401

Ale*_*oVK 6 python authentication django rest django-rest-framework

我发现很难弄清楚当令牌因某种原因在数据库中被删除时如何返回 401。

让我解释。

我的常规设置使用 SessionAuthentication 和 TokenAuthentication 方案。

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
    ),
    'DATETIME_FORMAT': '%a, %d %b %Y %H:%M:%S %z',
    'DATETIME_INPUT_FORMATS': ['iso-8601', '%Y-%m-%d %H:%M:%S', '%a, %d %b %Y %H:%M:%S %z'],
    'DATE_FORMAT': '%Y-%m-%d',
    'DATE_INPUT_FORMATS': ['%Y-%m-%d', '%m/%d/%YYYY'],
    'PAGE_SIZE': 20
}
Run Code Online (Sandbox Code Playgroud)

我有一个生成身份验证令牌的视图,如下所示:

class AcmeObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
    renderer_classes = (renderers.JSONRenderer,)
    serializer_class = AcmeAuthTokenSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.context = {'request': self.request}
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
       return Response({'token': token.key,
                     'school': school,
                     'user': user.id})

obtain_auth_token = AcmeObtainAuthToken.as_view()
Run Code Online (Sandbox Code Playgroud)

我的问题是,当存储在数据库中的令牌由于某种原因消失并且客户端发送令牌时,当我需要 401 时,我会得到 403。

看看文档,确实很神秘:

将使用的响应类型取决于身份验证方案。尽管可以使用多种认证方案,但是可以仅使用一种方案来确定响应的类型。在确定响应类型时,使用在视图上设置的第一个身份验证类别。

它说这取决于但如何呢?没有给出任何例子...关于 DRF 在幕后如何发挥其魔力有点令人困惑...

Joh*_*fis 4

403 是您在这种情况下应该得到的响应。看看这个链接

服务器理解该请求,但拒绝满足它。授权不会有帮助,并且不应重复请求。

本质上,客户端发出了正确的请求,但缺少令牌,因此他的访问被禁止(403)。

如果你确实想响应 401 错误,你可以在你的视图中尝试如下操作BloowatchObtainAuthToken

class BloowatchObtainAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        response = super(BloowatchObtainAuthToken, self).post(request, *args, **kwargs)
        try:
            token = Token.objects.get(user=request.user) # or what you are validating against
            other stuff here...
        except Token.DoesNotExist:
            return Response({'error': 'Token does not exist'}, status=401)
Run Code Online (Sandbox Code Playgroud)