CSRF Protection in Forms
Why CSRF Protection Exists
Without it, a malicious site could trick a logged-in user's browser into submitting a form to your app without their knowledge.
Example: Why CSRF Protection Exists
Without it, a malicious site could trick a logged-in user's browser into submitting a form to your app without their knowledge.
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
What Happens Without the Token
A POST request missing the csrf token is rejected by Django's middleware with a 403 Forbidden response, before your view even runs.
Example: What Happens Without the Token
A POST request missing the csrf token is rejected by Django's middleware with a 403 Forbidden response, before your view even runs.
# settings.py
MIDDLEWARE = [
# ...
'django.middleware.csrf.CsrfViewMiddleware',
# ...
]
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
CSRF Token in AJAX Requests
For JavaScript-driven POST requests, read the token from the cookie or a hidden input and send it as the X-CSRFToken header.
Example: CSRF Token in AJAX Requests
For JavaScript-driven POST requests, read the token from the cookie or a hidden input and send it as the X-CSRFToken header.
<script>
fetch('/save/', {
method: 'POST',
headers: {'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value},
body: new FormData(document.querySelector('form'))
});
</script>
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
- Omitting {% csrf_token %} from a POST form, causing Django to reject the submission with a 403 Forbidden error.
- Disabling CSRF protection globally to fix the error instead of adding the missing token tag.
- Forgetting that AJAX POST requests also need the CSRF token sent as a header, not just template forms.
- Django's CsrfViewMiddleware rejects POST requests that don't include a valid CSRF token.
- Every template form that submits via POST must include {% csrf_token %} inside the <form> tag.
- The token is unique per session, preventing other sites from forging requests to your app.
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: