58

The django csrf middleware can't be disabled. I've commented it out from my Middleware of my project but my logins are failing due to missing CSRF issues. I'm working from the Django trunk. How can CSRF cause issues if it is not enabled in middleware?

I have to disable it because there are lots of POST requests on my site that CSRF just breaks. Any feedback on how I can completely disable CSRF in a django trunk project?

The "new' CSRF framework from Django's trunk is also breaking an external site that is coming in and doing a POST on a URL I'm giving them (this is part of a restful API.) I can't disable the CSRF framework as I said earlier, how can I fix this?

MikeN
  • 45,039
  • 49
  • 151
  • 227

6 Answers6

127

Yes, Django csrf framework can be disabled.

To manually exclude a view function from being handled by any CSRF middleware, you can use the csrf_exempt decorator, found in the django.views.decorators.csrf module. For example: (see doc)

from django.views.decorators.csrf import csrf_exempt                                          
@csrf_exempt                                                                                  
def my_view:                                                                            
    return Httpresponse("hello world")

..and then remove {% csrf_token %} inside the forms from your template,or leave other things unchanged if you have not included it in your forms.

Kane Blueriver
  • 4,170
  • 4
  • 29
  • 48
Adriot
  • 1,287
  • 2
  • 8
  • 2
  • 1
    +1 much better to use the prescribed method to turn it off selectively, rather than turning it off everywhere! – Seth Jul 19 '10 at 20:01
  • 2
    I agree this should be the accepted answer. In general, don't hack a library when its API already provides the functionality you need. – Isaac Sutherland Nov 29 '10 at 16:59
  • This is really great if you want to reuse your old apps in your new projects. – juanefren Mar 17 '11 at 07:04
  • It is not the accepted answer because he is most probably using the default login in `urls.py` like this: `url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='login'),` – Nicu Surdu Nov 26 '11 at 22:48
  • A reminder: if you have other decorators in the same view the order is relevant: so place @csrf_exempt first. – Patrick Bassut Dec 13 '13 at 18:53
  • If in an app the majority of views should exclude this - for example when it is used as an http API service - decorating every single view function rapidly becomes very tedious. – Danny Staple Oct 10 '14 at 09:38
82

You can disable this in middleware.

In your settings.py add a line to MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = (

    myapp.disable.DisableCSRF, 

)

Create a disable.py in myapp with the following

class DisableCSRF(object):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

Basically if you set the _dont_enforce_csrf_checks in your request, you should be ok.

shreddd
  • 10,975
  • 9
  • 33
  • 34
  • Thanks! Just what I needed. I use Django's commenting system, but since the page that includes the form is cached, csrf validation wasn't working. – Kevin Renskers Apr 07 '11 at 12:47
  • 1
    This is the best way to disable csrf for the entire site, quite simple. To selectively disable, which was not the question, then you can use the other answer about @csrf_exempt – Pykler Oct 04 '11 at 18:03
  • This one is the one, the previous others were far too general or were just masquerading the fact of the csrf fail for the view. This one rightly disables for certain app, without masquerading the fails... – Javier Novoa C. Dec 29 '11 at 17:51
  • 2
    This works for Django Rest Framework, too. I was having problems using View and ResponseMixin together. – olive Sep 12 '12 at 18:41
11

See answers below this for a better solution. Since I wrote this, a lot has changed. There are now better ways to disable CSRF.

I feel your pain. It's not acceptable for a framework to change such fundamental functionality. Even if I want to start using this from now on, I have legacy sites on the same machine sharing a copy of django. Changes like this should require major version number revisions. 1.x --> 2.x.

Anyway, to fix it I just commented it out and have stopped updating Django as often.

File: django/middleware/csrf.py Around line 160:

            # check incoming token
#            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
#            if request_csrf_token != csrf_token:
#                if cookie_is_new:
#                    # probably a problem setting the CSRF cookie
#                    return reject("CSRF cookie not set.")
#                else:
#                    return reject("CSRF token missing or incorrect.")
Aaron
  • 316
  • 2
  • 6
  • 1
    Years has passed, but commenting this section seems for me to be still the best option. Other solutions worked for some but not all cases usually. – Drachenfels May 23 '16 at 15:15
5

In general, you shouldn't be disabling CSRF protection, since doing so opens up security holes. If you insist, though…

A new way of doing CSRF protection landed in trunk just recently. Is your site by chance still configured to do it the old way? Here are the docs for The New Way™ and here are the docs for The Old Way™.

Hank Gay
  • 70,339
  • 36
  • 160
  • 222
  • 1
    Thanks for the info, you didn't tell me how to disable CSRF completely, I have a production site which has stopped working for paying customers because I was blindsided by this "new" way of doing things that is not backwards compatible. But this is the issue that is causing the problem, I'm working on quickly updating to the new/legacy way. – MikeN Oct 30 '09 at 17:08
  • Here's some of the discussion from the developers' mailing list: http://groups.google.com/group/django-developers/browse_thread/thread/ac771d10d58340cb Maybe that will help with the disabling/updating. – Hank Gay Oct 30 '09 at 17:47
  • There is a view decorator to use: @csrf_exempt, if you put this decorator the CSRF framework will ignore its checking for that request. I'm stil pissed at how this CSRF trap was sprung, it is baked into the auth framework so you can't disable it if you use auth for sign-in. – MikeN Oct 30 '09 at 18:05
  • 4
    The new version has only just landed in the development trunk. You shouldn't be using development code for a production site - or if you do you should be aware of what all the changes are before you update. – Daniel Roseman Oct 30 '09 at 20:21
  • 2
    In his defense, tracking `trunk` was the recommended way to run Django for quite a while. Even though that has changed, I'm sure there are plenty of people who still do it. – Hank Gay Oct 31 '09 at 02:13
  • Yes! I'm going to start using a stable version of Django. I've been running a production money generating site off the dev. branch from before version 1.0 was released. Django is an amazing project, but this is the first time I've gotten burned by using the trunk. – MikeN Nov 02 '09 at 14:49
4

I simply tried removing the references to csrf middleware classes from my settings.py, it worked. Not sure if this is acceptable. Any comments? Below two lines were removed -

      'django.middleware.csrf.CsrfViewMiddleware',
      'django.middleware.csrf.CsrfResponseMiddleware',
Yateen
  • 41
  • 1
  • ok, got it. It broke my admin stuff, so, the patch solution seems the best (though not tried it). – Yateen Nov 13 '10 at 11:49
1

my django version is 1.11. the middleware should be like this:

from django.utils.deprecation import MiddlewareMixin


class DisableCSRF(MiddlewareMixin):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)
blackholll
  • 11
  • 1