Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POST method always return 403 Forbidden

I have read Django - CSRF verification failed and several questions (and answers) related to django and POST method. One of the best-but-not-working-for-me answer is https://stackoverflow.com/a/4707639/755319

All of the approved answers suggest at least 3 things:

  1. Use RequestContext as the third parameter of render_to_response_call
  2. Add {% csrf_token %} in every form with POST method
  3. Check the MIDDLEWARE_CLASSES in settings.py

I've done exactly as suggested, but the error still appeared. I use django 1.3.1 (from ubuntu 12.04 repository) and python 2.7 (default from ubuntu)

This is my View:

# 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)

and this is my template (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 %}

I've restarted the server, but the 403 forbidden error is still there, telling that CSRF verification failed.

I've 2 questions:

  1. How to fix this error?
  2. Why is it so hard to make a "POST" in django, I mean is there any specific reason to make it so verbose (I come from PHP, and never found such a problem before)?
like image 333
goFrendiAsgard Avatar asked May 19 '12 08:05

goFrendiAsgard


People also ask

How do I fix a 403 postman error?

The simple answer is; “You need to be given the correct access”. Without being given the correct access you'd technically be hacking the server, as it is specifically set up to restrict said access.

Why do I keep getting forbidden 403?

The 403 Forbidden error appears when your server denies you permission to access a page on your site. This is mainly caused by a faulty security plugin, a corrupt . htaccess file, or incorrect file permissions on your server.


2 Answers

I maybe wrong however I found the above solutions rather complex.

what worked for me was simply including my csrf token into my post request.

$.ajax({
    type: "POST",
    url: "/reports/",
    data: { csrfmiddlewaretoken: "{{ csrf_token }}",   // < here 
            state:"inactive" 
          },
    success: function() {
        alert("pocohuntus")
        console.log("prototype")
    }
})
like image 182
laycat Avatar answered Oct 06 '22 10:10

laycat


This answer is for people that may encounter this same problem in the future.

The CSRF {{csrf_token}} template tag that is required for forms in Django prevent against Cross Site Request Forgeries. CSRF makes it possible for a malicious site that has been visited by a client's browser to make requests to your own server. Hence the csrf_token provided by django makes it simple for your django server and site to be protected against this type of malicious attack. If your form is not protected by csrf_token, django returns a 403 forbidden page. This is a form of protection for your website especially when the token wasn't left out intentionally.

But there are scenarios where a django site would not want to protect its forms using the csrf_token. For instance, I developed a USSD application and a view function is required to receive a POST request from the USSD API. We should note that the POST request was not from a form on the client hence the risk of CSRF impossible, since a malicious site cannot submit requests. The POST request is received when a user dials a USSD code and not when a form is submitted.

In other words, there are situations where a function will need to get a POST request and there would not be the need of {{csrf_token}}.

Django provides us with a decorator @csrf_exempt. This decorator marks a view as being exempt from the protection ensured by the 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 also provides another decorator that performs the same function with {{csrf_token}}, but it doesn't reject incoming request. This decorator is @requires_csrf_token. For instance:

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

The last decorator that will be mentioned in this post does exactly the same thing as {{csrf_token}} and it is called @csrf_protect. However, the use of this decorator by itself is not best practice because you might forget to add it to your views. For instance:

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

Below are some links that will guide and explain better.

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

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

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

like image 40
Iyanuoluwa Ajao Avatar answered Oct 06 '22 10:10

Iyanuoluwa Ajao