Reputation:
I am new to Django and csrf tokens, so this is a total newb question. I have a simple checkmark box on detail.html:
<form action="/results/" method="post">{% csrf_token %}
<input type="checkbox" value="1" name="artists">
<p><input type="submit" value="Send" /></p>
</form>
results.html looks like this:
<ul>
{% for choice in poll %}
<li>{{ choice }} </li>
{% endfor %}
</ul>
views.py looks like this:
from django.shortcuts import render_to_response
from django.core.context_processors import csrf
def handle(request):
artists = {}
c = {}
c.update(csrf(request))
if request.method == 'POST':
artists = request.POST.getlist('artists')
return render_to_response('polls/results.html', {'poll': artists})
urls.py looks like this:
from django.conf.urls import patterns, url
from django.conf import settings
urlpatterns = patterns('',
url(r'^detail/$', 'django.views.generic.simple.direct_to_template', {'template': 'polls/detail.html'}),
url(r'^results/$', 'polls.views.handle'),
)
When I load 'detail.html' and viewsource, I see:
<form action="/results/" method="post"><div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='TVidKbDr1SCJUWIMWpPecN5tR862Chbo' /></div>
<input type="checkbox" value="1" name="artists">
<p><input type="submit" value="Send" /></p>
</form>
I have 2 questions:
Upvotes: 6
Views: 5714
Reputation: 239430
No, the purpose is not so attackers cannot see the value. CSRF (Cross-Site Request Forgery), as its name implies, is intended to prevent a third-party site or client from posting data anonymously to your form handler view. The CSRF token is generated on page load and must be matched in the responding view when the form is submitted. There's no way a third-party entity can provide a matching code (since it's generated internally in Django), and therefore, it is prevented from posting the form. The fact that it is a hidden field is merely so it is not presented to the user, since it's information that they don't need to know or alter. The idea that it's for any sort of protection is insanity as anyone who knows enough to attempt to attack your site, also knows how to view source.
I'm not sure where you picked that code up from, but it's unnecessary in the first place. Django's default behavior is to add the CSRF token to the context. You would only need to do it manually if you disabled CSRF protection on the view using the csrf_exempt
decorator, because you need to CSRF protect the view conditionally. However, if you did need to do that, the c
variable would need to be added to the context passed to render_to_response
:
c = {'poll': artists}
c.update(csrf(request)
...
return render_to_response('polls/results.html', c)
Upvotes: 7