web-dev-qa-db-fra.com

Interdit (403) La vérification de la CSRF a échoué. Demande abandonnée. Même en utilisant le {% csrf_token%}

j'essaie de me connecter à Django, mais j'obtiens cette erreur. Je vérifie la documentation de CSRF et rien ne fonctionne pour moi.

Voici le HTML:

<body>
  <section class="container">
    <div class="login">
      <h1>Login to Web App</h1>

      {% if form.errors %}
        <p class="error">Lo sentimos, la combinacion de usuario y contrasena no es correcta!</p>
      {% endif %}  

      <form action="/accounts/auth/" method="post">
      {% csrf_token %}  
      <input type='hidden' name='csrfmiddlewaretoken' value='randomchars'/>

        <p><input name="username" type="text" name="login" value="" placeholder="Username"></p>

        <p><input name="password" type="password" name="password" value="" placeholder="Password"></p>

        <p class="submit"><input type="submit" name="commit" value="Login"></p>
      </form>
    </div>
</body>

Comme vous le voyez ci-dessus, j'utilise le {% csrf_token%} et j'utilise 'Django.middleware.csrf.CsrfViewMiddleware' dans mes applications installées.

Et mes vues sont:

from Django.http import HttpResponse,HttpResponseRedirect
from Django.template.loader import get_template 
from Django.template import Context
from datetime import datetime
from Django.shortcuts import render_to_response
from Django.http import HttpResponseRedirect
from Django.contrib import auth
from Django.core.context_processors import csrf

from models import *
from Django.shortcuts import get_object_or_404
from forms import *
from Django.template.context import RequestContext
from Django.contrib.auth.decorators import login_required
from Django.contrib.auth import authenticate, login

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response('login.html', c)    


def auth_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        auth.login(request.user)
        return HttpResponse('/accounts/loggedin') 
    else:
        return HttpResponse('/accounts/invalid')

je redirige vers un autre fichier HTML où je n'utilise pas le {% csrf_token%}.

16
BismarthSantana

Théorie


Quelques éléments sont nécessaires au bon fonctionnement de la protection csrf (consultez la docs ):

  1. Votre navigateur doit accepter les cookies de votre serveur
  2. Assurez-vous que 'Django.middleware.csrf.CsrfViewMiddleware' est inclus en tant que middleware dans votre settings.py (vous pouvez également utiliser le décorateur csrf_protect () sur les vues que vous souhaitez protéger).
  3. Assurez-vous de transmettre le jeton csrf de Django.core.context_processors.csrf au gestionnaire de contexte.

Lorsque vous chargez votre page, consultez la source de la page à l'aide de votre navigateur préféré. N'ouvrez pas le fichier HTML de modèle, ouvrez l'URL qui pointe vers la vue contenant le formulaire. Regardez où vous avez placé le {% csrf_token %}. Si vous voyez quelque chose comme 

<input type='hidden' name='csrfmiddlewaretoken' value="jdwjwjefjwdjqwølksqøwkop2j3ofje" />

ça devrait aller. 

Par contre, si vous voyez NOTPROVIDED, quelque chose s’est mal passé lors de la création du jeton csrf. En cherchant dans le code source (context_processors.py et csrf.py), on peut trouver quoi:

  • csrf(request) renvoie {'csrf_token': 'NOTPROVIDED'} si get_token(request) ne renvoie aucun. 
  • get_token(request) renvoie request.META.get("CSRF_COOKIE", None)

Je suppose que cela signifie qu’il renverrait None si le cookie n’a pas été créé avec succès. 

Réparer


Pour vous, cela signifie que vous devez d'abord remplacer 

<form action="/accounts/auth/" method="post" {% csrf_token %}>

avec

<form action="/accounts/auth/" method="post">
{% csrf_token %}
(...)
</form>

Nous aimerions que le champ csrf soit à l'intérieur de <form>...</form>, pas de à l'intérieur de<form>. Comme le code est pour le moment, il sera converti en

<form action="/accounts/auth/" method="post" <input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />>

et nous aimerions plutôt

<form action="/accounts/auth/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />

Après cela, jetez un œil au code source et voyez si vous pouvez trouver le champ csrf. Si vous pouvez le voir, tout devrait fonctionner en théorie.

Vous pouvez également vérifier que le cookie csrf a été défini dans votre navigateur, par exemple. dans Chrome, cliquez avec le bouton droit sur la page Web et sélectionnez Insepect Element. Sélectionnez l'onglet Resources, puis cliquez sur les cookies. Vous devriez y trouver un nom de cookie csrftoken.

Si vous avez toujours des problèmes, revérifiez le middleware Tuple dans votre settings.py et vérifiez que votre navigateur accepte les cookies de votre serveur, comme décrit ci-dessus.

19
Steinar Lima

Effacez le cache de votre navigateur et réessayez. Peut-être utilise-t-il le jeton CSRF enregistré dans le cookie mis en cache.

1
Mohammad Etemaddar