Το Django μας παρέχει (προαιρετικά) το CSRF middleware του οποίου η δουλειά είναι να αποτρέπει τις επιθέσεις CSRF. Για να το πετύχει αυτό, στα response object βρίσκει τις φόρμες με POST method και “εισάγει” ένα ακόμα κρυφό field που περιέχει ένα token μοναδικό για το session. Στα POST request επιβεβαιώνει οτι το token υπάρχει και είναι σωστό.
Όλα ωραία και καλά, αλλα αυτός ο τρόπος έχει το πρόβλημα ότι όταν θέλουμε να κάνουμε AJAX κλήσεις με POST requests δεν θα δουλέψουν γιατί το CSRF middelware δεν θα βρεί tokens.
Για να λύσω αυτό το πρόβλημα με τον πιό απλό τρόπο έφτιαξα ένα template tag που παρέχει ένα token στα template μου.
Έτσι, για παράδειγμα στο YUI όταν κάνω το request είναι κάπως έτσι:
Μιας και βασίζεται στην ύπαρξη του sessionid στο cookie, αυτό το tag δεν θα μας δώσει token όταν ο χρήστης έχει απενεργοποιήσει τα cookies (κάτι που σπάει ένα σκασμό site οπότε δεν με πολυνοιάζει) και όταν είναι το πρώτο request στο site μας. (Μπορούμε όμως να ελέγξουμε αν υπάρχει το token και να πράξουμε κατάλληλα)
fromdjango.confimportsettingsfromdjango.utils.hashcompatimportmd5_constructorimportreclassCsrfNode(template.Node):"""Tag that provides a CSRF token in the context.Usage: {% csrf_token as token %}If the user has no cookies (cookies disabled, or this isthe first ever page view on the site, this tag will providean empty token. You can test that (eg to refresh the page)"""def__init__(self,var_name):self.var_name=var_namedefrender(self,context):SESSION_COOKIE_NAME=getattr(settings,"SESSION_COOKIE_NAME","sessionid")sess_key=context['request'].COOKIES.get(SESSION_COOKIE_NAME,None)ifnotsess_key:# User has no cookie. Empty token.token=""else:val=settings.SECRET_KEY+sess_keytoken=md5_constructor(val).hexdigest()context[self.var_name]=tokenreturn''@register.tag(name='csrf_token')defdo_csrf_token(parser,token):try:tag_name,params=token.contents.split(None,1)exceptValueError:msg="%r tag requires arguments"%token.contents.split()[0]raisetemplate.TemplateSyntaxError(msg)m=re.search(r'^as (\w+)$',params)ifnotm:msg="%r tag had invalid arguments"%tag_nameraisetemplate.TemplateSyntaxError(msg)var_name=m.groups()[0]returnCsrfNode(var_name)