Вы не можете получить доступ к телу после чтения из потока данных запроса при чтении JSON

В настоящее время я работаю над проектом, в котором пользователи смогут аутентифицироваться с помощью формы, которую я защитил токеном CSRF, но пока я забочусь только о стороне сервера, вот код:

@api_view(['POST'])
@csrf_protect
@permission_classes([AllowAny])
def login(request):
    if request.method != "POST":
      return JsonResponse({"error": "Seules les requêtes POST sont autorisées."},   status=status.HTTP_405_METHOD_NOT_ALLOWED)


try:
    # Lecture sécurisée des données
    data = json.loads(request.body)
    username = data.get("username")
    password = data.get("password")

    if not username or not password:
        return JsonResponse({"error": "Nom d'utilisateur et mot de passe sont requis."}, status=status.HTTP_400_BAD_REQUEST)

    # Recherche de l'utilisateur dans les deux tables
    user = None
    role = None

    try:
        user = Administrateur.objects.get(username=username)
        role = "admin"
    except Administrateur.DoesNotExist:
        pass

    if not user:
        try:
            user = Employes.objects.get(username=username)
            role = "employe"
        except Employes.DoesNotExist:
            pass

    if not user or not check_password(password, user.password):
        return JsonResponse({"error": "Identifiants incorrects."}, status=status.HTTP_401_UNAUTHORIZED)

    # Génération des tokens
    refresh = RefreshToken.for_user(user)
    
    # Réponse sécurisée
    response = JsonResponse({"username": user.username})

   

    # Stocker le JWT dans un cookie HttpOnly sécurisé
    response.set_cookie(
        key='access_token',
        value=str(refresh.access_token),
        httponly=True,
        secure=True,
        samesite='Strict',
        max_age=3600
    )

    # Stocker le rôle pour le frontend
    response.set_cookie(
        key='user_role',
        value=role,
        httponly=False,
        secure=True,
        samesite='Strict',
        max_age=3600
    )

    return response

except Exception as e:
    return JsonResponse({"error": f"Erreur inattendue : {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

Проблема, с которой я сталкиваюсь, заключается в том, что когда я отправляю данные с помощью Postman на сервер, он выдает мне эту ошибку:

{
    "error": "Erreur inattendue : You cannot access body after reading from request's data stream"
}

Что я сделал, чтобы попытаться устранить эту ошибку, так это отключил защиту CSRF, и код работает корректно, но как только я повторно активировал его, эта ошибка возвращается. Я просмотрел документацию по Django, но не нашел ничего об этом сообщении об ошибке.

Ваша проблема заключается в этой строке:

data = json.loads(request.body)

Из документации:

Запрос на доступ.ПУБЛИКАЦИЯ в промежуточном программном обеспечении до запуска представления или в process_view() не позволит любому представлению, запущенному после запуска промежуточного программного обеспечения, изменять обработчики загрузки для запроса, и обычно этого следует избегать.

Класс CsrfViewMiddleware можно считать исключением, поскольку он предоставляет декораторы csrf_exempt() и csrf_protect(), которые позволяют представлениям явно контролировать, в какой момент должна выполняться проверка CSRF. То есть, в общем, вы не можете использовать request.body и CsrfViewMiddleware одновременно.

Вы могли бы просто использовать request.data, поскольку вы, похоже, используете фреймворк Django REST:

https://www.django-rest-framework.org/tutorial/2-requests-and-responses/#request-objects

Основной функциональностью объекта Request является запрос.атрибут data, который аналогичен request.POST, но более полезен для работы с веб-API.

Вернуться на верх