CSRF cookie not set django...verification failed

18,995

Solution 1

I had the same problem, and resolved it by adding the ensure_csrf_cookie decorator to your view:

 from django.views.decorators.csrf import ensure_csrf_cookie
 @ensure_csrf_cookie
 def yourView(request):
     #...

It will set csrftoken in browser cookie and you can make ajax like this

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    crossDomain: false, // obviates need for sameOrigin test
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type)) {
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});
$.ajax({
        url: url,
        type: type,
        async: async,
        data: data,
        error: function (e) {},
        success: function (data) {
                returnFunction(data);
            }
    });

Solution 2

You use both means to pass CSRF token to template processor

c = {}
c.update(csrf(request))

and RequestContext, while one is enough, see docs. But you use it wrong place, for serving 'POST' request. Those requests are normally sent by your browser when it fills up a form and want to get results.

Your browser renders home.html sending GET request to a server, which is served by

t = get_template('home.html')
html = t.render(ResponseContext({'name':name}))
return HttpResponse(html)

part of your code. And there you do not use any mean to pass csrf token. So when your template processor get_template().render() is invoked, is has no token in its context, so simply ignores {% csrf_token %} code in template. So you have to either use RequestContext in t.render(...) part of view, or pass you c dict there.

You can check it inspecting generated form in a browser window.

UPDATE

In seetings.py add a comma after 'django.core.context_processors.csrf', the way it is now, it just contcatenates strings.

Should be:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.csrf',
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',

Solution 3

It seems that You have forgot to pass request to render

Django comes with a special Context class, django.template.RequestContext, that acts slightly differently than the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:

In addition to these, RequestContext always uses django.core.context_processors.csrf. This is a security related context processor required by the admin and other contrib apps, and, in case of accidental misconfiguration, it is deliberately hardcoded in and cannot be turned off by the TEMPLATE_CONTEXT_PROCESSORS setting.

So What You need is following

t = get_template('home.html')
c = RequestContext(request, {'name':name})
return HttpResponse(t.render(c))

If You wold like You can check django dock here https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext

Solution 4

Start from fixing your HTML (You forgot =):

<form method="POST" action="/search/save">
{% csrf_token %}
<textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
<input type="submit" value="Save Page"/>
</form>

Also:

def home_Page(request):
    #if request.method == 'GET':
    name='Awais you have visited my website :P'
    if request.method == 'POST':
        #name = request.POST.get('content')
        return render_to_response("search.html", {}, context_instance=RequestContext(request))

    return render_to_response("home.html", {'name':name}, context_instance=RequestContext(request))
Share:
18,995
Saad Abdullah
Author by

Saad Abdullah

Toptal: https://www.toptal.com/resume/saad-abdullah

Updated on June 13, 2022

Comments

  • Saad Abdullah
    Saad Abdullah about 2 years

    AoA I am new to Django, I am trying to get data from POST, but getting error CSRF cookie not set, I tried alot to find the solution on google and stackoverflow via google too, but failed

    here is the code

    views.py

        from django.http import HttpResponse
        from django.template.loader import get_template
        from django.template import Context
        from django.template import RequestContext
        from django.core.context_processors import csrf
        from django.shortcuts import render_to_response
    
    def search_Post(request):
        if request.method == 'POST':
                c = {}
            c.update(csrf(request))
            # ... view code here
                    return render_to_response("search.html", c)
    
    def search_Page(request):
        name='Awais you have visited my website :P'
        t = get_template('search.html')
        html = t.render(Context({'name':name}))
        return HttpResponse(html)
    

    HTML File

    <p>
              {{ name }}
                <form method="POST" action="/save/">
                  {% csrf_token %}
                  <textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
                  <input type="submit" value="Save Page"/>
                </form>
           <div>  Cant figure out any solution! :( </div>
    
     </p>
    

    url.py

     url(r'^home/$', 'contacts.views.home_Page'),
     url(r'^save/$', 'contacts.views.search_Post'),
     url(r'^edit/$', 'contacts.views.edit_Page'),
     url(r'^search/$', 'contacts.views.search_Page'),
    

    settings.py

    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.core.context_processors.csrf',
        'django.contrib.auth.context_processors.auth',
        'django.core.context_processors.debug',
        'django.core.context_processors.i18n',
        'django.core.context_processors.media',
        'django.core.context_processors.static',
        'django.core.context_processors.request',
        'django.contrib.messages.context_processors.messages'
    )
    
    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        # Uncomment the next line for simple clickjacking protection:
        # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    )
    
  • Saad Abdullah
    Saad Abdullah over 10 years
    could you plz interpret ?
  • Saad Abdullah
    Saad Abdullah over 10 years
    i have updated my question by correcting the 'action=' and replacing your code with mine one, it runs perfectly with GET but when i click the form button it gives me error...cookie not set...CSRF verification failed
  • alko
    alko over 10 years
    do you see csrf token in generated html?
  • Saad Abdullah
    Saad Abdullah over 10 years
    what is this ResponseContext?
  • Dmitry Demidenko
    Dmitry Demidenko over 10 years
    Check the rendered page. Do you have csrf field(hidden input) rendered?
  • Saad Abdullah
    Saad Abdullah over 10 years
    no, still get the error FORBIDDEN 403 'CSRF verification failed. Request aborted.' Reason given for failure: CSRF cookie not set.
  • Saad Abdullah
    Saad Abdullah over 10 years
    there is no csrf field in html page
  • oleg
    oleg over 10 years
    have You reload page after changes made?
  • Saad Abdullah
    Saad Abdullah over 10 years
    yup...i have restart the server and reload the page
  • Saad Abdullah
    Saad Abdullah over 10 years
    Updated by question with urls.py and used one request( you taught me alot) and render the page..still csrf field is missing in search.html and get the verification failed error on clicking the POST button...I have made another method for this...check above... and why sould I add colon? 'django.core.context_processors.csrf':, it gives me alist of error when I runserver
  • Saad Abdullah
    Saad Abdullah over 10 years
    problem is solved :) very thanks for your help... i was using this for GET t = get_template('home.html') c = RequestContext(request, {'name':name}) and for your mentioned code in POST...which gave me errors, Replacing the get_template with c = {'name': name} c.update(csrf(request)) solved the problem :) Once again thanks :)
  • alko
    alko over 10 years
    In that case I suggest you mark question answered, either choosing from existing answers or if you not feel it appropriate, adding your own.
  • Kevin Zhao
    Kevin Zhao about 8 years
    wow! This worked for me, so this keeps the csrf protection on your site, is that correct?
  • Alexandre V.
    Alexandre V. over 6 years
    This has nothing to do with the question. In addition to that, you have used the term DNS incorrectly. It does not make any sense to use the IP address instead of the hostname.