web-dev-qa-db-fra.com

POST méthode retourne toujours 403 Forbidden

J'ai lu Django - La vérification CSRF a échoué et plusieurs questions (et réponses) relatives à Django et à la méthode POST. Une des meilleures solutions, mais qui ne fonctionnent pas pour moi, est https://stackoverflow.com/a/4707639/755319

Toutes les réponses approuvées suggèrent au moins 3 choses:

  1. Utilisez RequestContext comme troisième paramètre de render_to_response_call
  2. Ajoutez {% csrf_token%} dans chaque formulaire avec la méthode POST
  3. Vérifiez les MIDDLEWARE_CLASSES dans settings.py

J'ai fait exactement comme suggéré, mais l'erreur est toujours apparue. J'utilise Django 1.3.1 (du référentiel Ubuntu 12.04) et Python 2.7 (par défaut d'ubuntu)

Ceci est mon point de vue:

# Create your views here.
from Django.template import RequestContext
from Django.http import HttpResponse
from Django.shortcuts import render_to_response
from models import BookModel

def index(request):
    return HttpResponse('Welcome to the library')

def search_form(request):
    return render_to_response('library/search_form.html')

def search(request):
    if request.method=='POST':
        if 'q' in request.POST:
            q=request.POST['q']
            bookModel = BookModel.objects.filter(title__icontains=q)
            result = {'books' : bookModel,}
            return render_to_response('library/search.html', result, context_instance=RequestContext(request))
        else:
            return search_form(request)
    else:
        return search_form(request)

et voici mon modèle (search_form.html):

{% extends "base.html" %}
{% block content %}
<form action="/library/search/" method="post">
    {% csrf_token %} 
    <input type="text" name="q">
    <input type="submit" value="Search">
</form>
{% endblock %}

J'ai redémarré le serveur, mais l'erreur 403 interdite est toujours là, indiquant que la vérification CSRF a échoué.

J'ai 2 questions:

  1. Comment réparer cette erreur?
  2. Pourquoi est-ce si difficile de faire un "POST" dans Django, y a-t-il une raison spécifique de le rendre aussi verbeux (je viens de PHP et je n'ai jamais trouvé un tel problème auparavant)?
13
goFrendiAsgard

Essayez de placer RequestContext dans render_to_response de la vue search_form 

context_instance=RequestContext(request)
3
zubinmehta

J'ai peut-être tort, mais j'ai trouvé les solutions ci-dessus plutôt complexes. 

ce qui a bien fonctionné pour moi, c’est tout simplement d’inclure mon jeton CSRF dans ma demande de publication.

$.ajax({
    type: "POST",
    url: "/reports/",
    data: { csrfmiddlewaretoken: "{{ csrf_token }}",   // < here 
            state:"inactive" 
          },
    success: function() {
        alert("pocohuntus")
        console.log("prototype")
    }
})
11
laycat

Le moyen le plus simple d'éviter de tels problèmes consiste à utiliser le raccourci render .

from Django.shortcuts import render
# .. your other imports

def search_form(request):
    return render(request, 'library/search_form.html')

def search(request):
    q = request.GET.get('q')
    results = BookModel.objects.all()
    if q:
        results = results.filter(title__icontains=q)
    return render(request, 'library/search.html', {'result': results})
5
Burhan Khalid

Cette réponse s'adresse aux personnes susceptibles de rencontrer ce même problème à l'avenir. 

La balise de modèle CSRF {{csrf_token}} requise pour les formulaires dans Django empêche la création de requêtes de type Cross Site Request. CSRF permet à un site malveillant visité par le navigateur d'un client de faire des requêtes sur votre propre serveur. Ainsi, le csrf_token fourni par Django simplifie la protection de votre serveur et de votre site Django contre ce type d'attaque malveillante. Si votre formulaire n'est pas protégé par csrf_token, Django renvoie une page 403 interdite. Il s'agit d'une forme de protection pour votre site Web, en particulier lorsque le jeton n'a pas été oublié intentionnellement. 

Mais il existe des scénarios dans lesquels un site Django ne voudrait pas protéger ses formulaires à l’aide de csrf_token. Par exemple, j'ai développé une application USSD et une fonction d'affichage est requise pour recevoir une demande POST de l'API USSD. Il convient de noter que la demande POST ne provenait pas d'un formulaire sur le client, ce qui rendait le risque de CSRF impossible, puisqu'un site malveillant ne peut pas soumettre de demandes. La demande POST est reçue lorsqu'un utilisateur compose un code USSD et non lorsqu'un formulaire est soumis. 

En d'autres termes, il existe des situations dans lesquelles une fonction doit obtenir une demande POST et où il n'est pas nécessaire d'utiliser {{csrf_token}}.

Django nous fournit un décorateur @csrf_exempt. Ce décorateur marque une vue comme étant exempte de la protection assurée par le middleware. 

from Django.views.decorators.csrf import csrf_exempt
from Django.http import HttpResponse

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

Django fournit également un autre décorateur qui remplit la même fonction avec {{csrf_token}}, mais il ne rejette pas les demandes entrantes. Ce décorateur est @requires_csrf_token. Par exemple:

@requires_csrf_token
def my_view(request):
    c = {}
    # ...
    return render(request, "a_template.html", c)

Le dernier décorateur mentionné dans cet article fait exactement la même chose que {{csrf_token}} et s'appelle @csrf_protect. Cependant, l'utilisation de ce décorateur en soi n'est pas la meilleure pratique car vous pourriez oublier de l'ajouter à vos points de vue. Par exemple:

@csrf_protect
def my_view(request):
    c = {}
    # ...
    return render(request, "a_template.html", c)

Vous trouverez ci-dessous des liens qui guideront et expliqueront mieux. 

https://docs.djangoproject.com/fr/1.7/ref/contrib/csrf/#module-Django.views.decorators.csrf

https://docs.djangoproject.com/fr/1.7/ref/contrib/csrf/

http://www.squarefree.com/securitytips/web-developers.html#CSRF

3
Iyanuoluwa Ajao

La réponse est 403 bcoz, Django requiert un jeton CSRF (inclus dans les données de publication) dans chaque POST demande que vous effectuez.

Il y a différentes façons de le faire, telles que:

L’acquisition du jeton à partir du cookie et de la méthode a été expliquée dans article entrez la description du lien ici

ou 

Vous pouvez y accéder depuis DOM en utilisant {{csrf_token}}, disponible dans le modèle. 

Alors maintenant, en utilisant la deuxième méthode:

var post_data = {
  ...
  'csrfmiddlewaretoken':"{{ csrf_token }}"
  ...
}
$.ajax({
  url:'url',
  type:'POST'
  data:post_data,
  success:function(data){
    console.log(data);
  },
  error:function(error){
    console.log(error);
  }
});
2
Hiro

Vous pouvez aussi utiliser 

direct_to_template(request, 'library/search.html', result) 

au lieu de

render_to_response('library/search.html', result, context_instance=RequestContext(request))

parce que direct_to_template ajoute RequestContext automatiquement. Notez cependant que direct_to_template sera obsolète et Django vous proposera d'utiliser CBV TemplateView à la place.

RequestContext vous permet d'utiliser des processeurs de contexte. Et voici votre erreur: {% csrf_token %} a généré une chaîne vide et vous avez 403.

0
San4ez

Vous devez utiliser RequestContext avec votre réponse 

par exemple dans le fichier view.py

from Django.template import RequestContext

def home(request):
    return render_to_response('home.html',RequestContext(request, {}))
0
DHaval Joshi