Package django :: Package contrib :: Package csrf :: Module middleware
[hide private]
[frames] | no frames]

Source Code for Module django.contrib.csrf.middleware

 1  """ 
 2  Cross Site Request Forgery Middleware. 
 3   
 4  This module provides a middleware that implements protection 
 5  against request forgeries from other sites.  
 6   
 7  """ 
 8  from django.conf import settings 
 9  from django.http import HttpResponseForbidden 
10  from django.utils.safestring import mark_safe 
11  import md5 
12  import re 
13  import itertools 
14   
15  _ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>') 
16   
17  _POST_FORM_RE = \ 
18      re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) 
19       
20  _HTML_TYPES = ('text/html', 'application/xhtml+xml')     
21   
22 -def _make_token(session_id):
23 return md5.new(settings.SECRET_KEY + session_id).hexdigest()
24
25 -class CsrfMiddleware(object):
26 """Django middleware that adds protection against Cross Site 27 Request Forgeries by adding hidden form fields to POST forms and 28 checking requests for the correct value. 29 30 In the list of middlewares, SessionMiddleware is required, and must come 31 after this middleware. CsrfMiddleWare must come after compression 32 middleware. 33 34 If a session ID cookie is present, it is hashed with the SECRET_KEY 35 setting to create an authentication token. This token is added to all 36 outgoing POST forms and is expected on all incoming POST requests that 37 have a session ID cookie. 38 39 If you are setting cookies directly, instead of using Django's session 40 framework, this middleware will not work. 41 """ 42
43 - def process_request(self, request):
44 if request.method == 'POST': 45 try: 46 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 47 except KeyError: 48 # No session, no check required 49 return None 50 51 csrf_token = _make_token(session_id) 52 # check incoming token 53 try: 54 request_csrf_token = request.POST['csrfmiddlewaretoken'] 55 except KeyError: 56 return HttpResponseForbidden(_ERROR_MSG) 57 58 if request_csrf_token != csrf_token: 59 return HttpResponseForbidden(_ERROR_MSG) 60 61 return None
62
63 - def process_response(self, request, response):
64 csrf_token = None 65 try: 66 cookie = response.cookies[settings.SESSION_COOKIE_NAME] 67 csrf_token = _make_token(cookie.value) 68 except KeyError: 69 # No outgoing cookie to set session, but 70 # a session might already exist. 71 try: 72 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 73 csrf_token = _make_token(session_id) 74 except KeyError: 75 # no incoming or outgoing cookie 76 pass 77 78 if csrf_token is not None and \ 79 response['Content-Type'].split(';')[0] in _HTML_TYPES: 80 81 # ensure we don't add the 'id' attribute twice (HTML validity) 82 idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), 83 itertools.repeat('')) 84 def add_csrf_field(match): 85 """Returns the matched <form> tag plus the added <input> element""" 86 return mark_safe(match.group() + "<div style='display:none;'>" + \ 87 "<input type='hidden' " + idattributes.next() + \ 88 " name='csrfmiddlewaretoken' value='" + csrf_token + \ 89 "' /></div>")
90 91 # Modify any POST forms 92 response.content = _POST_FORM_RE.sub(add_csrf_field, response.content) 93 return response
94