I'm trying to write a site in Django where the API URLs are the same as user-facing URLs. But I'm having trouble with pages which use POST requests and CSRF protection. For example, if I have a page /foo/add I want to be able to send POST requests to it in two ways:
I have found various ways of disabling CSRF, such as @csrf_exempt, but these all disable it for the entire view. Is there any way of enabling/disabling it at a more fine-grained level? Or am I just going to have to implement by own CSRF protection from scratch?
You can use the csrf_exempt decorator to disable CSRF protection for a particular view.
Yes, it is safe to disable if you have a different authentication mechanism that cannot be cloaked. For internal enterprise applications, not much of a concern. We had to disable it because it was interfering with our existing authentication mechanism.
CSRF protection works by checking for a secret in each POST request. This ensures that a malicious user cannot “replay” a form POST to your website and have another logged in user unwittingly submit that form. The malicious user would have to know the secret, which is user specific (using a cookie).
The CSRF token is like an alphanumeric code or random secret value that's peculiar to that particular site. Hence, no other site has the same code. In Django, the token is set by CsrfViewMiddleware in the settings.py file.
urls.py
If you manage your routes in urls.py
, you can wrap your desired routes with csrf_exempt()
to exclude them from the CSRF verification middleware.
for instance,
from django.views.decorators.csrf import csrf_exempt urlpatterns = patterns( # ... # Will exclude `/api/v1/test` from CSRF url(r'^api/v1/test', csrf_exempt(TestApiHandler.as_view())) # ... )
Some may find the use of the @csrf_exempt
decorator more suitable for their needs
for instance,
from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse @csrf_exempt def my_view(request): return HttpResponse('Hello world')
There is a section of Django's CSRF Protection documentation titled View needs protection for one path which describes a solution. The idea is to use @csrf_exempt
on the whole view, but when the API client header is not present or invalid, then call a function annotated with @csrf_protect
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With