6

我正在使用 Django Rest Framework 构建一个 REST API。我目前有一个问题,我的一些端点返回 HTTP 401 Unauthorized,而我的绝大多数端点返回正确的响应。对于身份验证,我将 JWT 令牌与 djangorestframework-simplejwt 一起使用。

我已将 Django 配置为将令牌身份验证与 djangorestframework-simplejwt 一起使用。

# rest framework config settings
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
        # 'rest_framework.permissions.AllowAny',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],

当我在请求中传递有效的访问令牌时,我的绝大多数端点都会返回有效数据。如果我没有发送有效的令牌,我会收到 HTTP 403。

另一方面,我有一些自定义 API 视图,无论我是否传递了有效令牌,它们都会返回 HTTP 401。

我已将代码包含在下面的一个有问题的视图中。

class CheckDifferentialView(generics.GenericAPIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [TokenAuthentication]
    serializer_class = QuizDifferentialSerializer

    def post(self, request, *args, **kwargs):
        """
            A function to check a quiz question and to update a user's record of questions answered
        """
        print(request.META)
        if 'answer' not in request.data:
            return JsonResponse({'Error': 'answer not found in request'}, status=status.HTTP_400_BAD_REQUEST)

        answer = get_object_or_404(Differential, pk=request.data['answer'])
        serializer = QuizDifferentialSerializer(answer)

        if answer.is_correct:
            pass
            # record correct results
        else:
            pass
            # record failed result

        return Response(serializer.data, status=status.HTTP_200_OK)

这是我用来测试我的 API 的脚本

import requests
import json

POST_LOGIN_URL = 'http://localhost:8000/api/v1/token/'
POST_URL= 'http://localhost:8000/api/v1/check_differential'
REQUEST_URL = 'http://localhost:8000/api/v1/users'

with requests.Session() as session:
    post = session.post(POST_LOGIN_URL, json={"username": "j", "monkey": "aphextwin21"})
    token = json.loads(post.text)['access']
    headers = {'Authorization': 'Bearer ' + token}

    r = session.post(POST_URL, headers=headers, json={"answer": "2"})
    # r = session.get(REQUEST_URL, headers=headers)
    print(token)

print(r.text, r.status_code)

期望的行为是,如果我向这个端点发送一个带有有效令牌的 POST 请求,它将授权我并继续它的一天。如果没有提供具有有效访问令牌的授权标头,那么我希望它拒绝该请求。


更新


热心的马丁请指出

authentication_classes = [TokenAuthentication]

覆盖了我的设置文件中的默认值。我不知道就 Django 而言,TokenAuthentication 和 JWTAuthentication 的处理方式不同。现在我知道了。

从我的观点中删除后authentication_classess = [TokenAuthentication],这些观点正在按应有的方式工作。

4

1 回答 1

8

视图的身份验证类明确设置为TokenAuthenticationonly。它不适用于 JWT 令牌。

 authentication_classes = [TokenAuthentication]

您要么删除它以让默认类处理它,要么将其更改为 accept JWTAuthentication

于 2019-10-18T10:08:42.667 回答