# forms.py from django import forms from django.conf import settings import hmac import hashlib import base64 import time from utils import random_chars from csrf_settings import * class SafeForm(forms.Form): # how long is the form valid (in seconds) FORM_TIMEOUT = 1800 csrf_field = forms.CharField(widget=forms.HiddenInput) def __init__(self, request, *args, **kwargs): # must have CsrfCookieMiddleware enabled assert CSRF_COOKIE_NAME in request.COOKIES super(SafeForm, self).__init__(*args, **kwargs) if not self.is_bound: # create an initial value for the field tstamp = str(int(time.time())) salt = random_chars(SALT_LENGTH) cookie = request.COOKIES[CSRF_COOKIE_NAME] sig = tstamp + salt + self.__class__.__name__ + cookie sig = hmac.new(settings.SECRET_KEY, sig, digestmod=hashlib.sha1).hexdigest() final = base64.b64encode('/'.join([tstamp, salt, sig])) self.fields['csrf_field'].initial = final else: self._csrf_cookie = request.COOKIES[CSRF_COOKIE_NAME] def clean_csrf_field(self): tstamp, salt, sig = base64.b64decode(self.cleaned_data['csrf_field']).split('/') new_sig = tstamp + salt + self.__class__.__name__ + self._csrf_cookie new_sig = hmac.new(settings.SECRET_KEY, new_sig, digestmod=hashlib.sha1).hexdigest() if sig != new_sig: raise forms.ValidationError, 'You are under attack!' if int(time.time()) - int(tstamp) > SafeForm.FORM_TIMEOUT: raise forms.ValidationError, 'Form session has expired' # middleware.py from csrf_settings import * from utils import random_chars class CsrfCookieMiddleware(object): def process_response(self, request, response): if CSRF_COOKIE_NAME not in request.COOKIES: response.set_cookie(CSRF_COOKIE_NAME, random_chars(CSRF_COOKIE_LENGTH)) return response # utils.py import string import random def random_chars(length): alphanum = string.ascii_letters + string.digits return ''.join(random.choice(alphanum) for i in range(length)) # csrf_settings.py CSRF_COOKIE_LENGTH = 40 CSRF_COOKIE_NAME = 'no_csrf' SALT_LENGTH = 4