如何在Django Rest Framework

时间:2017-06-21 07:18:05

标签: python django rest authentication django-rest-framework

我很难弄清楚当数据库因为某种原因删除了令牌时如何返回401。

让我解释一下。

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

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
}

我有一个生成Auth Token的视图,如下所示:

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

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

docs这真是神秘:

  

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

它说它取决于但是如何?没有给出一个例子......有点混淆DRF如何在这里引起它的魔力......

2 个答案:

答案 0 :(得分:2)

403是您应该在该实例中获得的响应。看看this link

  

服务器理解请求,但拒绝履行请求。授权无效,请求不应重复。

从本质上讲,客户端提出了正确的请求,但令牌丢失,因此禁止访问(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)

答案 1 :(得分:0)

我们可以重写restframework的exception_handler

在您的身份验证功能中:

msg = 'Token not valid'
raise exceptions.AuthenticationFailed(msg)

在覆盖中:

from rest_framework.views import exception_handler
def core_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if response is not None:
        detail = []
        for field, value in response.data.items():
            if isinstance(value, list):
                detail += value
            else:
                detail.append(value)
        response.data['detail'] = ' '.join(detail)
        if response.data['detail'] == 'Token not valid':
            response.status_code = 401