You cannot access body after reading from request's data stream while reading JSON
I am currently working on a project where users will be able to authenticate themselves thanks to a form that I protected with a CSRF token, but for now I only take care of the server side party, here is the code:
@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)
The problem I encounter is when I send data with Postman to the server, it sends me this error:
{
"error": "Erreur inattendue : You cannot access body after reading from request's data stream"
}
What I did to try to solve this error is to disable the CSRF protection, and the code works correctly, but as soon as I reactivated it this error comes back. I looked in the Django documentation, but I did not find anything about this error message.
Your issue is this line:
data = json.loads(request.body)
From the documentation:
Accessing request.POST inside middleware before the view runs or in process_view() will prevent any view running after the middleware from being able to modify the upload handlers for the request, and should normally be avoided.
The CsrfViewMiddleware class can be considered an exception, as it provides the csrf_exempt() and csrf_protect() decorators which allow views to explicitly control at what point the CSRF validation should occur. That is, in general, you can not use
request.body
andCsrfViewMiddleware
at the same time.
You could simply use request.data
since you seem to be using Django REST Framework:
https://www.django-rest-framework.org/tutorial/2-requests-and-responses/#request-objects
The core functionality of the Request object is the request.data attribute, which is similar to request.POST, but more useful for working with Web APIs.