Ticket #7167: 7167-safeform1.diff
File 7167-safeform1.diff, 5.7 KB (added by , 16 years ago) |
---|
-
django/contrib/csrf/tests.py
1 """ 2 3 >>> from django.conf import settings 4 >>> from django.http import HttpRequest 5 >>> from django.contrib.csrf.forms import SafeForm 6 7 >>> settings.SECRET_KEY='secret' 8 >>> settings.SESSION_COOKIE_NAME='session_id' 9 10 #If SafeForm is not passed a HttpRequest object, a ValueError is raised 11 >>> form=SafeForm() 12 Traceback (most recent call last): 13 ... 14 ValueError: SafeForm must be given a HttpRequest object 15 16 #if the user who made the request does not have the session cookie set, 17 #a csrf token cannot be generated, so the value for the token should be empty 18 >>> request=HttpRequest() 19 >>> form=SafeForm(request=request) 20 >>> form.csrf_token_field() 21 u'<input type=\"hidden\" name=\"_csrf_token\" id=\"id__csrf_token\" />' 22 23 #if a user that does not send any cookies tries to submit a form, 24 #SafeForm should automatically invalidate it 25 >>> request=HttpRequest() 26 >>> request.POST['_csrf_token']='2376e3ffd767c170fab368189b7e4799' 27 >>> form=SafeForm(request.POST, request=request) 28 >>> form.is_valid() 29 False 30 >>> form.non_field_errors() 31 [u'Your session has expired. Please refresh the page and submit the form again.'] 32 33 #if the request has a valid session ID cookie, generate a token for it 34 >>> request=HttpRequest() 35 >>> request.COOKIES['session_id']='abcde' 36 >>> form=SafeForm(request=request) 37 >>> form.csrf_token_field() 38 u'<input type=\"hidden\" name=\"_csrf_token\" value=\"2376e3ffd767c170fab368189b7e4799\" id=\"id__csrf_token\" />' 39 40 #if a user submits a form that doesn't have a csrf token at all, the form is not valid 41 >>> form=SafeForm(request.POST,request=request) 42 >>> form.is_valid() 43 False 44 >>> form.non_field_errors() 45 [u'Your session has expired. Please refresh the page and submit the form again.'] 46 47 #if a user submits a form with an incorrect csrf token, the form is not valid. 48 >>> request=HttpRequest() 49 >>> request.POST['_csrf_token']='hello' 50 >>> request.COOKIES['session_id']='abcde' 51 >>> form=SafeForm(request.POST,request=request) 52 >>> form.is_valid() 53 False 54 >>> form.non_field_errors() 55 [u'Your session has expired. Please refresh the page and submit the form again.'] 56 57 #if a user submits a form with the correct token, only then should is_valid() be True 58 >>> request=HttpRequest() 59 >>> request.POST['_csrf_token']='2376e3ffd767c170fab368189b7e4799' 60 >>> request.COOKIES['session_id']='abcde' 61 >>> form=SafeForm(request.POST,request=request) 62 >>> form.is_valid() 63 True 64 65 """ 66 67 if __name__ == '__main__': 68 import doctest 69 doctest.testmod() -
django/contrib/csrf/forms.py
1 from django import forms 2 from django.conf import settings 3 from django.utils.hashcompat import md5_constructor 4 from django.utils.safestring import mark_safe 5 6 class SafeForm(forms.Form): 7 """ 8 Form that adds protection against Cross Site Request Forgeries by adding 9 a hidden field and checking for the correct value during validation. 10 11 It works virtually the same as a regular form, with the exception of an 12 additional parameter passed to the constructor - an HttpRequest object. 13 It uses the request object to get the user's session ID. 14 15 If the developer is manually specifying each field in their forms rather 16 than calling form.as_table or some other helper, they will also need to 17 add {{form.csrf_token_field}} somewhere inside the form in their template 18 19 This form does not rely on django.contrib.sessions to work as long as 20 whatever backend is ultimately used honors the settings.SESSION_COOKIE_NAME 21 setting. If that cookie is unset, safeform.is_valid() will always be false 22 """ 23 24 _csrf_token = forms.CharField(widget=forms.HiddenInput, required=False) 25 INVALID_TOKEN_MSG = "Your session has expired. Please refresh the "\ 26 + "page and submit the form again." 27 28 def __init__(self, *args, **kwargs): 29 try: 30 self._request=kwargs.pop('request') 31 except KeyError: 32 raise ValueError("SafeForm must be given a HttpRequest object") 33 34 super(SafeForm,self).__init__(*args, **kwargs) 35 36 #We cannot set the initial in the field declaration because the 37 #_make_token call needs the reference to "self" 38 self.fields['_csrf_token'].initial=self._make_token 39 40 def clean(self): 41 session_token = self._make_token() 42 43 if '_csrf_token' not in self.cleaned_data or self.cleaned_data['_csrf_token'] != session_token or session_token is None: 44 raise forms.ValidationError(self.INVALID_TOKEN_MSG) 45 46 return self.cleaned_data 47 48 49 def _make_token(self): 50 try: 51 session_id = self._request.COOKIES[settings.SESSION_COOKIE_NAME] 52 return md5_constructor(settings.SECRET_KEY + session_id).hexdigest() 53 except KeyError: 54 #if the user does not have any cookies set, 55 #a token cannot be generated 56 return None 57 58 def csrf_token_field(self): 59 return mark_safe(unicode(self['_csrf_token'])) 60 No newline at end of file -
AUTHORS
425 425 ymasuda@ethercube.com 426 426 Jarek Zgoda <jarek.zgoda@gmail.com> 427 427 Cheng Zhang 428 Elliott Mahler <join.together@gmail.com> 428 429 429 430 A big THANK YOU goes to: 430 431