Ticket #9977: csrf_template_tag_and_no_session_dep.5.diff
File csrf_template_tag_and_no_session_dep.5.diff, 65.3 KB (added by , 15 years ago) |
---|
-
django/conf/project_template/settings.py
60 60 MIDDLEWARE_CLASSES = ( 61 61 'django.middleware.common.CommonMiddleware', 62 62 'django.contrib.sessions.middleware.SessionMiddleware', 63 'django.contrib.csrf.middleware.CsrfViewMiddleware', 63 64 'django.contrib.auth.middleware.AuthenticationMiddleware', 64 65 ) 65 66 … … 74 75 INSTALLED_APPS = ( 75 76 'django.contrib.auth', 76 77 'django.contrib.contenttypes', 78 'django.contrib.csrf', 77 79 'django.contrib.sessions', 78 80 'django.contrib.sites', 79 81 ) -
django/conf/global_settings.py
165 165 'django.core.context_processors.debug', 166 166 'django.core.context_processors.i18n', 167 167 'django.core.context_processors.media', 168 'django.contrib.csrf.context_processors.csrf', 168 169 # 'django.core.context_processors.request', 169 170 ) 170 171 … … 303 304 MIDDLEWARE_CLASSES = ( 304 305 'django.middleware.common.CommonMiddleware', 305 306 'django.contrib.sessions.middleware.SessionMiddleware', 307 'django.contrib.csrf.middleware.CsrfViewMiddleware', 306 308 'django.contrib.auth.middleware.AuthenticationMiddleware', 307 309 # 'django.middleware.http.ConditionalGetMiddleware', 308 310 # 'django.middleware.gzip.GZipMiddleware', … … 377 379 # The number of days a password reset link is valid for 378 380 PASSWORD_RESET_TIMEOUT_DAYS = 3 379 381 382 ######## 383 # CSRF # 384 ######## 385 386 # Cookie name and domain to store the CSRF authentication token. 387 CSRF_COOKIE_NAME = 'authid' 388 CSRF_COOKIE_DOMAIN = None 389 390 # Dotted path to callable to be used as view when a request is 391 # rejected by the CSRF middleware. 392 CSRF_FAILURE_VIEW = 'django.contrib.csrf.views.csrf_failure' 393 380 394 ########### 381 395 # TESTING # 382 396 ########### -
django/contrib/formtools/templates/formtools/preview.html
1 1 {% extends "base.html" %} 2 2 {% load csrf %} 3 3 {% block content %} 4 4 5 5 <h1>Preview your submission</h1> … … 15 15 16 16 <p>Security hash: {{ hash_value }}</p> 17 17 18 <form action="" method="post"> 18 <form action="" method="post">{% csrf_token %} 19 19 {% for field in form %}{{ field.as_hidden }} 20 20 {% endfor %} 21 21 <input type="hidden" name="{{ stage_field }}" value="2" /> … … 25 25 26 26 <h1>Or edit it again</h1> 27 27 28 <form action="" method="post"> 28 <form action="" method="post">{% csrf_token %} 29 29 <table> 30 30 {{ form }} 31 31 </table> -
django/contrib/formtools/templates/formtools/form.html
1 1 {% extends "base.html" %} 2 2 {% load csrf %} 3 3 {% block content %} 4 4 5 5 {% if form.errors %}<h1>Please correct the following errors</h1>{% else %}<h1>Submit</h1>{% endif %} 6 6 7 <form action="" method="post"> 7 <form action="" method="post">{% csrf_token %} 8 8 <table> 9 9 {{ form }} 10 10 </table> -
django/contrib/comments/templates/comments/approve.html
1 1 {% extends "comments/base.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block title %}{% trans "Approve a comment" %}{% endblock %} 5 5 6 6 {% block content %} 7 7 <h1>{% trans "Really make this comment public?" %}</h1> 8 8 <blockquote>{{ comment|linebreaks }}</blockquote> 9 <form action="." method="post"> 9 <form action="." method="post">{% csrf_token %} 10 10 {% if next %}<input type="hidden" name="next" value="{{ next }}" id="next" />{% endif %} 11 11 <p class="submit"> 12 12 <input type="submit" name="submit" value="{% trans "Approve" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a> -
django/contrib/comments/templates/comments/preview.html
1 1 {% extends "comments/base.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block title %}{% trans "Preview your comment" %}{% endblock %} 5 5 6 6 {% block content %} 7 7 {% load comments %} 8 <form action="{% comment_form_target %}" method="post"> 8 <form action="{% comment_form_target %}" method="post">{% csrf_token %} 9 9 {% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %} 10 10 {% if form.errors %} 11 11 <h1>{% blocktrans count form.errors|length as counter %}Please correct the error below{% plural %}Please correct the errors below{% endblocktrans %}</h1> -
django/contrib/comments/templates/comments/delete.html
1 1 {% extends "comments/base.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block title %}{% trans "Remove a comment" %}{% endblock %} 5 5 6 6 {% block content %} 7 7 <h1>{% trans "Really remove this comment?" %}</h1> 8 8 <blockquote>{{ comment|linebreaks }}</blockquote> 9 <form action="." method="post"> 9 <form action="." method="post">{% csrf_token %} 10 10 {% if next %}<input type="hidden" name="next" value="{{ next }}" id="next" />{% endif %} 11 11 <p class="submit"> 12 12 <input type="submit" name="submit" value="{% trans "Remove" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a> -
django/contrib/comments/templates/comments/form.html
1 {% load comments i18n %}2 <form action="{% comment_form_target %}" method="post"> 1 {% load comments i18n csrf %} 2 <form action="{% comment_form_target %}" method="post">{% csrf_token %} 3 3 {% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %} 4 4 {% for field in form %} 5 5 {% if field.is_hidden %} -
django/contrib/comments/templates/comments/moderation_queue.html
1 1 {% extends "admin/change_list.html" %} 2 {% load adminmedia i18n %}2 {% load adminmedia i18n csrf %} 3 3 4 4 {% block title %}{% trans "Comment moderation queue" %}{% endblock %} 5 5 … … 44 44 {% for comment in comments %} 45 45 <tr class="{% cycle 'row1' 'row2' %}"> 46 46 <td class="actions"> 47 <form action="{% url comments-approve comment.pk %}" method="post"> 47 <form action="{% url comments-approve comment.pk %}" method="post">{% csrf_token %} 48 48 <input type="hidden" name="next" value="{% url comments-moderation-queue %}" /> 49 49 <input class="approve submit" type="submit" name="submit" value="{% trans "Approve" %}" /> 50 50 </form> 51 <form action="{% url comments-delete comment.pk %}" method="post"> 51 <form action="{% url comments-delete comment.pk %}" method="post">{% csrf_token %} 52 52 <input type="hidden" name="next" value="{% url comments-moderation-queue %}" /> 53 53 <input class="remove submit" type="submit" name="submit" value="{% trans "Remove" %}" /> 54 54 </form> -
django/contrib/comments/templates/comments/flag.html
1 1 {% extends "comments/base.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block title %}{% trans "Flag this comment" %}{% endblock %} 5 5 6 6 {% block content %} 7 7 <h1>{% trans "Really flag this comment?" %}</h1> 8 8 <blockquote>{{ comment|linebreaks }}</blockquote> 9 <form action="." method="post"> 9 <form action="." method="post">{% csrf_token %} 10 10 {% if next %}<input type="hidden" name="next" value="{{ next }}" id="next" />{% endif %} 11 11 <p class="submit"> 12 12 <input type="submit" name="submit" value="{% trans "Flag" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a> -
django/contrib/admin/templates/admin/change_list.html
1 1 {% extends "admin/base_site.html" %} 2 {% load adminmedia admin_list i18n %}2 {% load adminmedia admin_list i18n csrf %} 3 3 4 4 {% block extrastyle %} 5 5 {{ block.super }} … … 68 68 {% endif %} 69 69 {% endblock %} 70 70 71 <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}> 71 <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %} 72 72 {% if cl.formset %} 73 73 {{ cl.formset.management_form }} 74 74 {% endif %} -
django/contrib/admin/templates/admin/template_validator.html
1 1 {% extends "admin/base_site.html" %} 2 2 {% load csrf %} 3 3 {% block content %} 4 4 5 5 <div id="content-main"> 6 6 7 <form action="" method="post"> 7 <form action="" method="post">{% csrf_token %} 8 8 9 9 {% if form.errors %} 10 10 <p class="errornote">Your template had {{ form.errors|length }} error{{ form.errors|pluralize }}:</p> -
django/contrib/admin/templates/admin/delete_selected_confirmation.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block breadcrumbs %} 5 5 <div class="breadcrumbs"> … … 23 23 {% for deleteable_object in deletable_objects %} 24 24 <ul>{{ deleteable_object|unordered_list }}</ul> 25 25 {% endfor %} 26 <form action="" method="post"> 26 <form action="" method="post">{% csrf_token %} 27 27 <div> 28 28 {% for obj in queryset %} 29 29 <input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk }}" /> … … 34 34 </div> 35 35 </form> 36 36 {% endif %} 37 {% endblock %} 38 No newline at end of file 37 {% endblock %} -
django/contrib/admin/templates/admin/auth/user/change_password.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n admin_modify adminmedia %}2 {% load i18n admin_modify adminmedia csrf %} 3 3 {% block extrahead %}{{ block.super }} 4 4 <script type="text/javascript" src="../../../../jsi18n/"></script> 5 5 {% endblock %} … … 15 15 </div> 16 16 {% endif %}{% endblock %} 17 17 {% block content %}<div id="content-main"> 18 <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}18 <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %} 19 19 <div> 20 20 {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} 21 21 {% if form.errors %} -
django/contrib/admin/templates/admin/login.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block extrastyle %}{% load adminmedia %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/login.css" />{% endblock %} 5 5 … … 14 14 <p class="errornote">{{ error_message }}</p> 15 15 {% endif %} 16 16 <div id="content-main"> 17 <form action="{{ app_path }}" method="post" id="login-form"> 17 <form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %} 18 18 <div class="form-row"> 19 19 <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" /> 20 20 </div> -
django/contrib/admin/templates/admin/change_form.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n admin_modify adminmedia %}2 {% load i18n admin_modify adminmedia csrf %} 3 3 4 4 {% block extrahead %}{{ block.super }} 5 5 <script type="text/javascript" src="../../../jsi18n/"></script> … … 29 29 </ul> 30 30 {% endif %}{% endif %} 31 31 {% endblock %} 32 <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}32 <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %} 33 33 <div> 34 34 {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} 35 35 {% if save_on_top %}{% submit_row %}{% endif %} -
django/contrib/admin/templates/admin/delete_confirmation.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block breadcrumbs %} 5 5 <div class="breadcrumbs"> … … 22 22 {% else %} 23 23 <p>{% blocktrans with object as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p> 24 24 <ul>{{ deleted_objects|unordered_list }}</ul> 25 <form action="" method="post"> 25 <form action="" method="post">{% csrf_token %} 26 26 <div> 27 27 <input type="hidden" name="post" value="yes" /> 28 28 <input type="submit" value="{% trans "Yes, I'm sure" %}" /> -
django/contrib/admin/templates/registration/password_reset_confirm.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password reset confirmation' %}</div>{% endblock %} 5 5 … … 13 13 14 14 <p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p> 15 15 16 <form action="" method="post"> 16 <form action="" method="post">{% csrf_token %} 17 17 {{ form.new_password1.errors }} 18 18 <p class="aligned wide"><label for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}</p> 19 19 {{ form.new_password2.errors }} -
django/contrib/admin/templates/registration/password_reset_form.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 4 4 {% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password reset' %}</div>{% endblock %} 5 5 … … 11 11 12 12 <p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p> 13 13 14 <form action="" method="post"> 14 <form action="" method="post">{% csrf_token %} 15 15 {{ form.email.errors }} 16 16 <p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <input type="submit" value="{% trans 'Reset my password' %}" /></p> 17 17 </form> -
django/contrib/admin/templates/registration/password_change_form.html
1 1 {% extends "admin/base_site.html" %} 2 {% load i18n %}2 {% load i18n csrf %} 3 3 {% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %} {% trans 'Change password' %} / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %} 4 4 {% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %} 5 5 … … 11 11 12 12 <p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p> 13 13 14 <form action="" method="post"> 14 <form action="" method="post">{% csrf_token %} 15 15 16 16 {{ form.old_password.errors }} 17 17 <p class="aligned wide"><label for="id_old_password">{% trans 'Old password:' %}</label>{{ form.old_password }}</p> -
django/contrib/admin/sites.py
3 3 from django.contrib.admin import ModelAdmin 4 4 from django.contrib.admin import actions 5 5 from django.contrib.auth import authenticate, login 6 from django.contrib.csrf.middleware import csrf_response_exempt 6 7 from django.db.models.base import ModelBase 7 8 from django.core.exceptions import ImproperlyConfigured 8 9 from django.shortcuts import render_to_response … … 156 157 raise ImproperlyConfigured("Put 'django.contrib.admin' in your INSTALLED_APPS setting in order to use the admin application.") 157 158 if not ContentType._meta.installed: 158 159 raise ImproperlyConfigured("Put 'django.contrib.contenttypes' in your INSTALLED_APPS setting in order to use the admin application.") 160 if 'django.contrib.csrf' not in settings.INSTALLED_APPS: 161 raise ImproperlyConfigured("Put 'django.contrib.csrf' in your INSTALLED_APPS setting in order to use the admin application.") 159 162 if 'django.core.context_processors.auth' not in settings.TEMPLATE_CONTEXT_PROCESSORS: 160 163 raise ImproperlyConfigured("Put 'django.core.context_processors.auth' in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.") 164 if 'django.contrib.csrf.context_processors.csrf' not in settings.TEMPLATE_CONTEXT_PROCESSORS: 165 raise ImproperlyConfigured("Put 'django.contrib.csrf.context_processors.csrf' in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.") 161 166 162 167 def admin_view(self, view): 163 168 """ … … 182 187 if not self.has_permission(request): 183 188 return self.login(request) 184 189 return view(request, *args, **kwargs) 185 return update_wrapper(inner, view) 190 inner = update_wrapper(inner, view) 191 return csrf_response_exempt(inner) 186 192 187 193 def get_urls(self): 188 194 from django.conf.urls.defaults import patterns, url, include -
django/contrib/csrf/middleware.py
5 5 against request forgeries from other sites. 6 6 """ 7 7 8 import itertools 8 9 import re 9 import itertools10 import random 10 11 try: 11 12 from functools import wraps 12 13 except ImportError: 13 14 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 14 15 15 16 from django.conf import settings 16 from django. http import HttpResponseForbidden17 from django.core.urlresolvers import get_callable 17 18 from django.utils.hashcompat import md5_constructor 18 19 from django.utils.safestring import mark_safe 19 20 20 _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>')21 22 21 _POST_FORM_RE = \ 23 22 re.compile(r'(<form\W[^>]*\bmethod\s*=\s*(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) 24 23 25 24 _HTML_TYPES = ('text/html', 'application/xhtml+xml') 26 25 27 def _make_token(session_id): 26 # Use the system (hardware-based) random number generator if it exists. 27 if hasattr(random, 'SystemRandom'): 28 randrange = random.SystemRandom().randrange 29 else: 30 randrange = random.randrange 31 _MAX_CSRF_KEY = 18446744073709551616L # 2 << 63 32 33 def _get_failure_view(): 34 """ 35 Returns the view to be used for CSRF rejections 36 """ 37 return get_callable(settings.CSRF_FAILURE_VIEW) 38 39 def _get_new_csrf_key(): 40 return md5_constructor("%s%s" 41 % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest() 42 43 def _make_legacy_session_token(session_id): 28 44 return md5_constructor(settings.SECRET_KEY + session_id).hexdigest() 29 45 46 def get_token(request): 47 """ 48 Returns the the CSRF token required for a POST form, or None if the CSRF middleware 49 is not installed. 50 """ 51 return request.META.get("CSRF_COOKIE", None) 52 30 53 class CsrfViewMiddleware(object): 31 54 """ 32 55 Middleware that requires a present and correct csrfmiddlewaretoken 33 for POST requests that have an active session. 56 for POST requests that have a CSRF cookie, and sets an outgoing 57 CSRF cookie. 58 59 This middleware should be used in conjunction with the csrf_token template 60 tag. 34 61 """ 35 62 def process_view(self, request, callback, callback_args, callback_kwargs): 63 if getattr(callback, 'csrf_exempt', False): 64 return None 65 66 # If the user doesn't have a CSRF cookie, generate one and store it in the 67 # request, so it's available to the view. We'll store it in a cookie when 68 # we reach the response. 69 try: 70 request.META["CSRF_COOKIE"] = request.COOKIES[settings.CSRF_COOKIE_NAME] 71 cookie_is_new = False 72 except KeyError: 73 # No cookie, so create one. 74 request.META["CSRF_COOKIE"] = _get_new_csrf_key() 75 cookie_is_new = True 76 36 77 if request.method == 'POST': 37 if getattr(callback, 'csrf_exempt', False):38 return None39 40 78 if request.is_ajax(): 41 79 return None 42 80 43 try: 44 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 45 except KeyError: 46 # No session, no check required 47 return None 81 # If the user didn't already have a CSRF key, then accept the 82 # session key for the middleware token, so CSRF protection isn't lost 83 # for the period between upgrading to CSRF cookes to the first time 84 # each user comes back to the site to receive one. 85 if cookie_is_new: 86 try: 87 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 88 csrf_token = _make_legacy_session_token(session_id) 89 except KeyError: 90 # No CSRF cookie and no session cookie; no check is performed. 91 return None 92 else: 93 csrf_token = request.META["CSRF_COOKIE"] 48 94 49 csrf_token = _make_token(session_id)50 95 # check incoming token 51 try: 52 request_csrf_token = request.POST['csrfmiddlewaretoken'] 53 except KeyError: 54 return HttpResponseForbidden(_ERROR_MSG) 55 96 request_csrf_token = request.POST.get('csrfmiddlewaretoken', None) 56 97 if request_csrf_token != csrf_token: 57 return HttpResponseForbidden(_ERROR_MSG)98 return _get_failure_view()(request) 58 99 59 100 return None 60 101 102 def process_response(self, request, response): 103 # If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was 104 # never called, probaby because a request middleware returned a response 105 # (for example, contrib.auth redirecting to a login page). 106 if request.META.get("CSRF_COOKIE") is None: 107 return response 108 109 # Set the CSRF cookie even if it's already set, so we renew the expiry timer. 110 response.set_cookie(settings.CSRF_COOKIE_NAME, 111 request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52, 112 domain=settings.CSRF_COOKIE_DOMAIN) 113 114 return response 115 61 116 class CsrfResponseMiddleware(object): 62 117 """ 63 Middleware that post-processes a response to add a 64 csrfmiddlewaretoken if the response/request have an active 65 session. 118 Middleware that post-processes a response to add a csrfmiddlewaretoken. 119 120 It is recommended to use the csrf_token template tag instead of 121 this middleware. 66 122 """ 67 123 def process_response(self, request, response): 68 124 if getattr(response, 'csrf_exempt', False): 69 125 return response 70 126 71 csrf_token = None 72 try: 73 # This covers a corner case in which the outgoing response 74 # both contains a form and sets a session cookie. This 75 # really should not be needed, since it is best if views 76 # that create a new session (login pages) also do a 77 # redirect, as is done by all such view functions in 78 # Django. 79 cookie = response.cookies[settings.SESSION_COOKIE_NAME] 80 csrf_token = _make_token(cookie.value) 81 except KeyError: 82 # Normal case - look for existing session cookie 83 try: 84 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 85 csrf_token = _make_token(session_id) 86 except KeyError: 87 # no incoming or outgoing cookie 88 pass 127 if response['Content-Type'].split(';')[0] in _HTML_TYPES: 128 csrf_token = get_token(request) 129 # If csrf_token is None, we have no token for this request, which probably 130 # means that this is a response from a request middleware. 131 if csrf_token is None: 132 return response 89 133 90 if csrf_token is not None and \91 response['Content-Type'].split(';')[0] in _HTML_TYPES:92 93 134 # ensure we don't add the 'id' attribute twice (HTML validity) 94 135 idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), 95 136 itertools.repeat('')) 96 137 def add_csrf_field(match): 97 138 """Returns the matched <form> tag plus the added <input> element""" 98 139 return mark_safe(match.group() + "<div style='display:none;'>" + \ … … 104 145 response.content = _POST_FORM_RE.sub(add_csrf_field, response.content) 105 146 return response 106 147 107 class CsrfMiddleware(CsrfViewMiddleware, CsrfResponseMiddleware): 108 """Django middleware that adds protection against Cross Site 148 class CsrfMiddleware(object): 149 """ 150 Django middleware that adds protection against Cross Site 109 151 Request Forgeries by adding hidden form fields to POST forms and 110 152 checking requests for the correct value. 111 153 112 In the list of middlewares, SessionMiddleware is required, and 113 must come after this middleware. CsrfMiddleWare must come after 114 compression middleware. 154 CsrfMiddleware uses two middleware, CsrfViewMiddleware and 155 CsrfResponseMiddleware, which can be used independently. It is recommended 156 to use only CsrfViewMiddleware and use the csrf_token template tag in 157 templates for inserting the token. 158 """ 159 # We can't just inherit from CsrfViewMiddleware and CsrfResponseMiddleware 160 # because both have process_response methods. 161 def __init__(self): 162 self.response_middleware = CsrfResponseMiddleware() 163 self.view_middleware = CsrfViewMiddleware() 115 164 116 If a session ID cookie is present, it is hashed with the117 SECRET_KEY setting to create an authentication token. This token118 is added to all outgoing POST forms and is expected on all119 incoming POST requests that have a session ID cookie.165 def process_response(self, request, resp): 166 # We must do the cookie setting before the post-processing 167 resp2 = self.view_middleware.process_response(request, resp) 168 return self.response_middleware.process_response(request, resp2) 120 169 121 If you are setting cookies directly, instead of using Django's 122 session framework, this middleware will not work. 170 def process_view(self, request, callback, callback_args, callback_kwargs): 171 return self.view_middleware.process_view(request, callback, callback_args, 172 callback_kwargs) 123 173 124 CsrfMiddleWare is composed of two middleware, CsrfViewMiddleware125 and CsrfResponseMiddleware which can be used independently.126 """127 pass128 129 174 def csrf_response_exempt(view_func): 130 175 """ 131 176 Modifies a view function so that its response is exempt -
django/contrib/csrf/views.py
1 from django.http import HttpResponseForbidden 2 from django.utils.safestring import mark_safe 3 4 _ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>CSRF verification failed. Request aborted.</p></body></html>') 5 6 def csrf_failure(request): 7 """ 8 Default view used when request fails CSRF protection 9 """ 10 return HttpResponseForbidden(_ERROR_MSG) -
django/contrib/csrf/tests.py
2 2 3 3 from django.test import TestCase 4 4 from django.http import HttpRequest, HttpResponse, HttpResponseForbidden 5 from django.contrib.csrf.middleware import CsrfMiddleware, _make_token, csrf_exempt 5 from django.contrib.csrf.middleware import CsrfMiddleware, CsrfViewMiddleware, csrf_exempt 6 from django.contrib.csrf.context_processors import csrf 7 from django.contrib.sessions.middleware import SessionMiddleware 8 from django.utils.importlib import import_module 6 9 from django.conf import settings 10 from django.template import RequestContext, Template 7 11 8 12 # Response/views used for CsrfResponseMiddleware and CsrfViewMiddleware tests 9 13 def post_form_response(): 10 14 resp = HttpResponse(content=""" 11 15 <html><body><form method="POST"><input type="text" /></form></body></html> 12 16 """, mimetype="text/html") 13 17 return resp 14 18 15 def test_view(request): 19 def post_form_response_non_html(): 20 resp = post_form_response() 21 resp["Content-Type"] = "application/xml" 22 return resp 23 24 def post_form_view(request): 16 25 return post_form_response() 17 26 27 # Response/views used for template tag tests 28 def _token_template(): 29 return Template("{% load csrf %}{% csrf_token %}") 30 31 def _render_csrf_token_template(req): 32 context = RequestContext(req, processors=[csrf]) 33 template = _token_template() 34 return template.render(context) 35 36 def token_view(request): 37 return HttpResponse(_render_csrf_token_template(request)) 38 18 39 class CsrfMiddlewareTest(TestCase): 40 _csrf_id = "1" 19 41 42 # This is a valid session token for this ID and secret key. This was generated using 43 # the old code that we're to be backwards-compatible with. Don't use the CSRF code 44 # to generate this hash, or we're merely testing the code against itself and not 45 # checking backwards-compatibility. This is also the output of (echo -n test1 | md5sum). 46 _session_token = "5a105e8b9d40e1329780d62ea2265d8a" 20 47 _session_id = "1" 48 _secret_key_for_session_test= "test" 21 49 22 def _get_GET_no_ session_request(self):50 def _get_GET_no_csrf_cookie_request(self): 23 51 return HttpRequest() 24 52 25 def _get_GET_ session_request(self):26 req = self._get_GET_no_session_request()27 req.COOKIES[settings. SESSION_COOKIE_NAME] = self._session_id53 def _get_GET_csrf_cookie_request(self): 54 req = HttpRequest() 55 req.COOKIES[settings.CSRF_COOKIE_NAME] = self._csrf_id 28 56 return req 29 57 30 def _get_POST_ session_request(self):31 req = self._get_GET_ session_request()58 def _get_POST_csrf_cookie_request(self): 59 req = self._get_GET_csrf_cookie_request() 32 60 req.method = "POST" 33 61 return req 34 62 35 def _get_POST_no_ session_request(self):36 req = self._get_GET_no_ session_request()63 def _get_POST_no_csrf_cookie_request(self): 64 req = self._get_GET_no_csrf_cookie_request() 37 65 req.method = "POST" 38 66 return req 39 67 68 def _get_POST_request_with_token(self): 69 req = self._get_POST_csrf_cookie_request() 70 req.POST['csrfmiddlewaretoken'] = self._csrf_id 71 return req 72 40 73 def _get_POST_session_request_with_token(self): 41 req = self._get_POST_session_request() 42 req.POST['csrfmiddlewaretoken'] = _make_token(self._session_id) 74 req = self._get_POST_no_csrf_cookie_request() 75 req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id 76 req.POST['csrfmiddlewaretoken'] = self._session_token 43 77 return req 44 78 45 def _get_post_form_response(self): 46 return post_form_response() 79 def _get_POST_session_request_no_token(self): 80 req = self._get_POST_no_csrf_cookie_request() 81 req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id 82 return req 47 83 48 def _get_new_session_response(self): 49 resp = self._get_post_form_response() 50 resp.cookies[settings.SESSION_COOKIE_NAME] = self._session_id 51 return resp 84 def _check_token_present(self, response, csrf_id=None): 85 self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % (csrf_id or self._csrf_id)) 52 86 53 def _check_token_present(self, response): 54 self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % _make_token(self._session_id)) 55 56 def get_view(self): 57 return test_view 58 59 # Check the post processing 60 def test_process_response_no_session(self): 87 # Check the post processing and outgoing cookie 88 def test_process_response_no_csrf_cookie(self): 61 89 """ 62 Check the the post-processor does nothing if no session active 90 When no prior CSRF cookie exists, check that the cookie is created and a 91 token is inserted. 63 92 """ 64 req = self._get_GET_no_session_request() 65 resp = self._get_post_form_response() 93 req = self._get_GET_no_csrf_cookie_request() 94 CsrfMiddleware().process_view(req, post_form_view, (), {}) 95 96 resp = post_form_response() 66 97 resp_content = resp.content # needed because process_response modifies resp 67 98 resp2 = CsrfMiddleware().process_response(req, resp) 68 self.assertEquals(resp_content, resp2.content)69 99 70 def test_process_response_existing_session(self): 100 csrf_cookie = resp2.cookies.get(settings.CSRF_COOKIE_NAME, False) 101 self.assertNotEqual(csrf_cookie, False) 102 self.assertNotEqual(resp_content, resp2.content) 103 self._check_token_present(resp2, csrf_cookie.value) 104 105 def test_process_response_no_csrf_cookie_view_only(self): 71 106 """ 72 Check that the token is inserted if there is an existing session 107 When no prior CSRF cookie exists, check that the cookie is created, even 108 if only CsrfViewMiddleware is used. 73 109 """ 74 req = self._get_GET_session_request() 75 resp = self._get_post_form_response() 110 # The CsrfViewMiddleware must have the cookie setting code. 111 req = self._get_GET_no_csrf_cookie_request() 112 CsrfViewMiddleware().process_view(req, post_form_view, (), {}) 113 resp = post_form_view(req) 114 resp2 = CsrfViewMiddleware().process_response(req, resp) 115 116 csrf_cookie = resp2.cookies.get(settings.CSRF_COOKIE_NAME, False) 117 self.assertNotEqual(csrf_cookie, False) 118 119 def test_process_response_existing_csrf_cookie(self): 120 """ 121 Check that the token is inserted when a prior CSRF cookie exists 122 """ 123 req = self._get_GET_csrf_cookie_request() 124 CsrfMiddleware().process_view(req, post_form_view, (), {}) 125 126 resp = post_form_response() 76 127 resp_content = resp.content # needed because process_response modifies resp 77 128 resp2 = CsrfMiddleware().process_response(req, resp) 78 129 self.assertNotEqual(resp_content, resp2.content) 79 130 self._check_token_present(resp2) 80 131 81 def test_process_response_n ew_session(self):132 def test_process_response_non_html(self): 82 133 """ 83 134 Check that the token is inserted if there is a new session being started 135 Check the the post-processor does nothing for content-types not in _HTML_TYPES. 84 136 """ 85 req = self._get_GET_no_session_request() # no session in request 86 resp = self._get_new_session_response() # but new session started 137 req = self._get_GET_no_csrf_cookie_request() 138 CsrfMiddleware().process_view(req, post_form_view, (), {}) 139 resp = post_form_response_non_html() 87 140 resp_content = resp.content # needed because process_response modifies resp 88 141 resp2 = CsrfMiddleware().process_response(req, resp) 89 self.assertNotEqual(resp_content, resp2.content) 90 self._check_token_present(resp2) 142 self.assertEquals(resp_content, resp2.content) 91 143 92 144 def test_process_response_exempt_view(self): 93 145 """ 94 146 Check that no post processing is done for an exempt view 95 147 """ 96 req = self._get_POST_ session_request()97 resp = csrf_exempt( self.get_view())(req)148 req = self._get_POST_csrf_cookie_request() 149 resp = csrf_exempt(post_form_view)(req) 98 150 resp_content = resp.content 99 151 resp2 = CsrfMiddleware().process_response(req, resp) 100 152 self.assertEquals(resp_content, resp2.content) 101 153 102 154 # Check the request processing 103 def test_process_request_no_session (self):155 def test_process_request_no_session_no_csrf_cookie(self): 104 156 """ 105 Check that if n o session is present, the middleware does nothing.106 to the incoming request.157 Check that if neither a CSRF cookie nor a session cookie are present, the 158 middleware does nothing to the incoming request. 107 159 """ 108 req = self._get_POST_no_ session_request()109 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})160 req = self._get_POST_no_csrf_cookie_request() 161 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 110 162 self.assertEquals(None, req2) 111 163 112 def test_process_request_ session_no_token(self):164 def test_process_request_csrf_cookie_no_token(self): 113 165 """ 114 Check that if a session is present but no token, we get a 'forbidden'166 Check that if a CSRF cookie is present but no token, we get a 'forbidden'. 115 167 """ 116 req = self._get_POST_ session_request()117 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})168 req = self._get_POST_csrf_cookie_request() 169 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 118 170 self.assertEquals(HttpResponseForbidden, req2.__class__) 119 171 120 def test_process_request_ session_and_token(self):172 def test_process_request_csrf_cookie_and_token(self): 121 173 """ 122 Check that if a session is present and a token, the middleware lets it through174 Check that if both a cookie and a token is present, the middleware lets it through. 123 175 """ 124 req = self._get_POST_ session_request_with_token()125 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})176 req = self._get_POST_request_with_token() 177 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 126 178 self.assertEquals(None, req2) 127 179 128 def test_process_request_session_ no_token_exempt_view(self):180 def test_process_request_session_cookie_no_csrf_cookie_token(self): 129 181 """ 130 Check that if a session is present and no token, but the csrf_exempt 182 When no CSRF cookie exists, but the user has a session, check that a token 183 using the session cookie as a legacy CSRF cookie is accepted. 184 """ 185 orig_secret_key = settings.SECRET_KEY 186 settings.SECRET_KEY = self._secret_key_for_session_test 187 try: 188 req = self._get_POST_session_request_with_token() 189 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 190 self.assertEquals(None, req2) 191 finally: 192 settings.SECRET_KEY = orig_secret_key 193 194 def test_process_request_session_cookie_no_csrf_cookie_no_token(self): 195 """ 196 Check that if a session cookie is present but no token and no CSRF cookie, 197 we get a 'forbidden'. 198 """ 199 req = self._get_POST_session_request_no_token() 200 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 201 self.assertEquals(HttpResponseForbidden, req2.__class__) 202 203 def test_process_request_csrf_cookie_no_token_exempt_view(self): 204 """ 205 Check that if a CSRF cookie is present and no token, but the csrf_exempt 131 206 decorator has been applied to the view, the middleware lets it through 132 207 """ 133 req = self._get_POST_ session_request()134 req2 = CsrfMiddleware().process_view(req, csrf_exempt( self.get_view()), (), {})208 req = self._get_POST_csrf_cookie_request() 209 req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {}) 135 210 self.assertEquals(None, req2) 136 211 137 212 def test_ajax_exemption(self): 138 213 """ 139 214 Check that AJAX requests are automatically exempted. 140 215 """ 141 req = self._get_POST_ session_request()216 req = self._get_POST_csrf_cookie_request() 142 217 req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' 143 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})218 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 144 219 self.assertEquals(None, req2) 220 221 # Tests for the template tag method 222 def test_token_node_no_csrf_cookie(self): 223 """ 224 Check that CsrfTokenNode works when no CSRF cookie is set 225 """ 226 req = self._get_GET_no_csrf_cookie_request() 227 resp = token_view(req) 228 self.assertEquals(u"", resp.content) 229 230 def test_token_node_with_csrf_cookie(self): 231 """ 232 Check that CsrfTokenNode works when a CSRF cookie is set 233 """ 234 req = self._get_GET_csrf_cookie_request() 235 CsrfViewMiddleware().process_view(req, token_view, (), {}) 236 resp = token_view(req) 237 self._check_token_present(resp) 238 239 def test_token_node_with_new_csrf_cookie(self): 240 """ 241 Check that CsrfTokenNode works when a CSRF cookie is created by 242 the middleware (when one was not already present) 243 """ 244 req = self._get_GET_no_csrf_cookie_request() 245 CsrfViewMiddleware().process_view(req, token_view, (), {}) 246 resp = token_view(req) 247 resp2 = CsrfViewMiddleware().process_response(req, resp) 248 csrf_cookie = resp2.cookies[settings.CSRF_COOKIE_NAME] 249 self._check_token_present(resp, csrf_id=csrf_cookie.value) 250 251 def test_response_middleware_without_view_middleware(self): 252 """ 253 Check that CsrfResponseMiddleware finishes without error if the view middleware 254 has not been called, as is the case if a request middleware returns a response. 255 """ 256 req = self._get_GET_no_csrf_cookie_request() 257 resp = post_form_view(req) 258 CsrfMiddleware().process_response(req, resp) -
django/contrib/csrf/templatetags/csrf.py
1 from django import template 2 from django.utils.safestring import mark_safe 3 4 register = template.Library() 5 6 class CsrfTokenNode(template.Node): 7 def render(self, context): 8 csrf_token = context.get('csrf_token', None) 9 if csrf_token: 10 if csrf_token == 'NOTNEEDED': 11 return mark_safe(u"") 12 else: 13 return mark_safe(u"<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='%s' /></div>" % (csrf_token)) 14 else: 15 # It's very probable that the token is missing because of 16 # misconfiguration, so we raise a warning 17 from django.conf import settings 18 if settings.DEBUG: 19 import warnings 20 warnings.warn("A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not having 'django.contrib.csrf.context_processors.csrf' in TEMPLATE_CONTEXT_PROCESSORS.") 21 return u'' 22 23 def csrf_token(parser, token): 24 return CsrfTokenNode() 25 register.tag(csrf_token) -
django/contrib/csrf/templatetags/__init__.py
1 -
django/contrib/csrf/context_processors.py
1 from django.contrib.csrf.middleware import get_token 2 from django.utils.functional import memoize 3 4 def csrf(request): 5 """ 6 Context processor that provides a CSRF token, or the string 7 'NOTNEEDED' if it is not needed 8 """ 9 def _get_val(): 10 token = get_token(request) 11 if token is None: 12 # In order to be able to provide debugging info in the 13 # case of misconfiguration, we use a sentinel value 14 # instead of returning an empty dict. 15 return 'NOTNEEDED' 16 else: 17 return token 18 _get_val = memoize(_get_val, {}, 0) 19 20 return {'csrf_token': _get_val() } -
tests/regressiontests/admin_views/tests.py
811 811 # 4 action inputs (3 regular checkboxes, 1 checkbox to select all) 812 812 # main form submit button = 1 813 813 # search field and search submit button = 2 814 # 6 + 2 + 1 + 2 = 11 inputs 815 self.failUnlessEqual(response.content.count("<input"), 15) 814 # csrf hidden field = 1 815 # 6 + 2 + 4 + 1 + 2 + 1 = 16 inputs 816 self.failUnlessEqual(response.content.count("<input"), 16) 816 817 # 1 select per object = 3 selects 817 818 self.failUnlessEqual(response.content.count("<select"), 4) 818 819 -
tests/runtests.py
30 30 'django.contrib.sessions', 31 31 'django.contrib.comments', 32 32 'django.contrib.admin', 33 'django.contrib.csrf', 33 34 ] 34 35 35 36 def get_test_models(): -
AUTHORS
463 463 Gasper Zejn <zejn@kiberpipa.org> 464 464 Jarek Zgoda <jarek.zgoda@gmail.com> 465 465 Cheng Zhang 466 Glenn 467 bthomas 466 468 467 469 A big THANK YOU goes to: 468 470 -
docs/topics/http/middleware.txt
29 29 MIDDLEWARE_CLASSES = ( 30 30 'django.middleware.common.CommonMiddleware', 31 31 'django.contrib.sessions.middleware.SessionMiddleware', 32 'django.contrib.csrf.middleware.CsrfViewMiddleware', 32 33 'django.contrib.auth.middleware.AuthenticationMiddleware', 33 34 ) 34 35 -
docs/ref/contrib/csrf.txt
7 7 .. module:: django.contrib.csrf 8 8 :synopsis: Protects against Cross Site Request Forgeries 9 9 10 The C srfMiddleware classprovides easy-to-use protection against10 The CSRF middleware and template tag provides easy-to-use protection against 11 11 `Cross Site Request Forgeries`_. This type of attack occurs when a malicious 12 12 Web site creates a link or form button that is intended to perform some action 13 on your Web site, using the credentials of a logged-in user who is tricked 14 intoclicking on the link in their browser.13 on your Web site, using the credentials of a logged-in user who is tricked into 14 clicking on the link in their browser. 15 15 16 The first defense against CSRF attacks is to ensure that GET requests 17 are side-effect free. POST requests can then be protected by adding this 18 middleware into your list of installed middleware .16 The first defense against CSRF attacks is to ensure that GET requests are 17 side-effect free. POST requests can then be protected by adding these 18 middleware into your list of installed middleware following the steps below. 19 19 20 .. versionadded:: 1.1 21 The 'contrib' apps, including the admin, depend on the functionality 22 described here. Anyone upgrading from earlier versions should read 23 the `Upgrading notes`_ carefully. 24 20 25 .. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF 21 26 22 27 How to use it 23 28 ============= 24 29 25 Add the middleware ``'django.contrib.csrf.middleware.CsrfMiddleware'`` to 26 your list of middleware classes, :setting:`MIDDLEWARE_CLASSES`. It needs to process 27 the response after the SessionMiddleware, so must come before it in the 28 list. It also must process the response before things like compression 29 happen to the response, so it must come after GZipMiddleware in the 30 list. 30 .. versionchanged:: 1.1 31 The template tag functionality (the recommended way to use this) was added 32 in version 1.1. The previous method (still available) is described under 33 `Legacy method`_. 31 34 32 The ``CsrfMiddleware`` class is actually composed of two middleware: 33 ``CsrfViewMiddleware`` which performs the checks on incoming requests, 34 and ``CsrfResponseMiddleware`` which performs post-processing of the 35 result. This allows the individual components to be used and/or 36 replaced instead of using ``CsrfMiddleware``. 35 To enable CSRF protection for your views, follow these steps: 37 36 38 .. versionchanged:: 1.1 39 (previous versions of Django did not provide these two components 40 of ``CsrfMiddleware`` as described above) 37 1. Add the middleware 38 ``'django.contrib.csrf.middleware.CsrfViewMiddleware'`` to your list of 39 middleware classes, :setting:`MIDDLEWARE_CLASSES`. (It should come 40 before ``CsrfResponseMiddleware`` if that is being used, and before any 41 view middleware that assume that CSRF attacks have been dealt with.) 41 42 43 2. Add ``'django.contrib.csrf'`` to your :setting:`INSTALLED_APPS`. 44 45 3. In any template that uses a POST form, first load the 'csrf' template tag 46 library:: 47 48 {% load csrf %} 49 50 Then use the ``csrf_token`` tag inside the ``<form>`` element, e.g.:: 51 52 <form action="" method="POST">{% csrf_token %} 53 54 4. In the corresponding view functions, ensure that the 55 ``'django.contrib.csrf.context_processors.csrf'`` context processor is 56 being used. Usually, this can be done in one of two ways: 57 58 1. Using RequestContext: 59 60 1. Ensure ``'django.contrib.csrf.context_processors.csrf'`` is present 61 in your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. It is 62 present by default. 63 64 2. Use ``RequestContext`` as the context instance in the relevant 65 views. If you are using generic views or contrib apps, you are 66 covered already. 67 68 2. Manually import and use the processor to generate the CSRF token and 69 add it to the template context. e.g.:: 70 71 from django.contrib.csrf.context_processors import csrf 72 from django.template import Context 73 from django.shortcuts import render_to_response 74 def my_view(request): 75 c = Context() 76 c.update(csrf(request)) 77 return render_to_response("a_template.html", context_instance=c) 78 79 Legacy method 80 ------------- 81 82 In Django 1.0, the template tag did not exist. Instead, a post-processing 83 middleware that re-wrote POST forms to include the CRSF token was used. If you 84 are upgrading a site from version 1.0 or earlier, please read this section and 85 the `Upgrading notes`_ below. The post-processing middleware is still available 86 as ``CsrfResponseMiddleware``, and it can be used by following these steps: 87 88 1. Follow step 1 above to install ``CsrfViewMiddleware``. 89 90 2. Add ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'`` to your 91 :setting:`MIDDLEWARE_CLASSES` setting. 92 93 ``CsrfResponseMiddleware`` needs to process the response before things 94 like compression happen to the response, so it must come after 95 ``GZipMiddleware`` in the list. It also must come after 96 ``CsrfViewMiddleware``. 97 98 Use of the ``CsrfResponseMiddleware`` is not recommended because of the 99 performance hit it imposes. It can be used as an interim measure until 100 applications have been updated to use the ``{% crsf_token %}`` tag. 101 102 Django 1.0 provided a single ``CsrfMiddleware`` class. This is also still 103 available for backwards compatibility. It combines the functions of the two new 104 middleware. 105 106 Note also that previous versions of these classes depended on the sessions 107 framework, but this dependency has now been removed, with backward compatibility 108 support so that upgrading will not produce any issues. 109 110 Upgrading notes 111 --------------- 112 113 When upgrading to version 1.1 or later, you may have applications that rely on 114 the old post-processing functionality for CSRF protection, or you may not have 115 enabled any CSRF protection. This section outlines the steps necessary for a 116 smooth upgrade, without having to fix all the applications to use the new 117 template tag method immediately. 118 119 If you are using any of the contrib apps (such as the admin), there are some 120 required steps for these applications to continue working. First, the CSRF 121 application must be added to :setting:`INSTALLED_APPS` (See `How to use it`_ 122 above, step 2). Second, the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting must 123 be updated (step 4.1.1 above). 124 125 If you have ``CsrfMiddleware`` in your :setting:`MIDDLEWARE_CLASSES`, you will now 126 have a working installation with CSRF protection. It is recommended at this 127 point that you replace ``CsrfMiddleware`` with its two components, 128 ``CsrfViewMiddleware`` and ``CsrfResponseMiddleware`` (in that order). 129 130 If you do not have any of the middleware in your :setting:`MIDDLEWARE_CLASSES`, 131 you will have a working installation but without any CSRF protection (just as 132 you had before). It is recommended to install ``CsrfViewMiddleware`` and 133 ``CsrfResponseMiddleware``, but if you are not interested in having any CSRF 134 protection, you can simply stop here. 135 136 Assuming you have followed the above, all views in your Django site will now be 137 protected by the ``CsrfViewMiddleware``. Contrib apps meet the requirements 138 imposed by the ``CsrfViewMiddleware`` using the template tag, and other 139 applications in your project will meet its requirements by virtue of the 140 ``CsrfResponseMiddleware``. 141 142 The next step is to update all your applications to use the template tag, as 143 described in `How to use it`_, steps 3-4. This can be done as soon as is 144 practical. Any applications that are updated will now require Django 1.1 or 145 later, since they will use the CSRF template tag library which was not available 146 in earlier versions. 147 148 Finally, once all applications are upgraded, ``CsrfResponseMiddleware`` can be 149 removed from your settings. 150 151 While ``CsrfResponseMiddleware`` is still in use, the ``csrf_response_exempt`` 152 decorator, described in `Exceptions`_, may be useful. The post-processing 153 middleware imposes a performance hit, and any views that have been upgraded to 154 use the new template tag method no longer need it. Using this decorator will 155 allow you to avoid this performance hit. 156 42 157 Exceptions 43 158 ---------- 44 159 45 160 .. versionadded:: 1.1 46 161 47 To manually exclude a view function from being handled by the48 CsrfMiddleware, you can use the ``csrf_exempt`` decorator, found in 49 the``django.contrib.csrf.middleware`` module. For example::162 To manually exclude a view function from being handled by either of the two CSRF 163 middleware, you can use the ``csrf_exempt`` decorator, found in the 164 ``django.contrib.csrf.middleware`` module. For example:: 50 165 51 166 from django.contrib.csrf.middleware import csrf_exempt 52 167 … … 54 169 return HttpResponse('Hello world') 55 170 my_view = csrf_exempt(my_view) 56 171 57 Like the middleware itself, the ``csrf_exempt`` decorator is composed58 of two parts: a ``csrf_view_exempt`` decorator and a 59 ``csrf_response_exempt`` decorator, found in the same module. These 60 disable the view protection mechanism (``CsrfViewMiddleware``) and the 61 response post-processing (``CsrfResponseMiddleware``) respectively. 62 They can be used individually ifrequired.172 Like the middleware, the ``csrf_exempt`` decorator is composed of two parts: a 173 ``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` decorator, found 174 in the same module. These disable the view protection mechanism 175 (``CsrfViewMiddleware``) and the response post-processing 176 (``CsrfResponseMiddleware``) respectively. They can be used individually if 177 required. 63 178 64 You don't have to worry about doing this for most AJAX views. Any 65 request sent with "X-Requested-With: XMLHttpRequest" is automatically 66 exempt. (See the nextsection.)179 You don't have to worry about doing this for most AJAX views. Any request sent 180 with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the next 181 section.) 67 182 183 Rejected requests 184 ================= 185 186 By default, a '403 Forbidden' response is sent to the user if an incoming 187 request fails the checks performed by ``CsrfViewMiddleware``. This should 188 usually only be seen when there is a genuine Cross Site Request Forgery, or 189 when, due to a programming error, the CSRF token has not been included with a 190 POST form. 191 192 No logging is done, and the error message is not very friendly, so you may want 193 to provide your own page for handling this condition. To do this, simply set 194 the :setting:`CSRF_FAILURE_VIEW` setting to a dotted path to your own view 195 function. 196 68 197 How it works 69 198 ============ 70 199 71 CsrfMiddleware does twothings:200 The CSRF protection is based on three things: 72 201 73 1. It modifies outgoing requests by adding a hidden form field to all 74 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is 75 a hash of the session ID plus a secret. If there is no session ID set, 76 this modification of the response isn't done, so there is very little 77 performance penalty for those requests that don't have a session. 78 (This is done by ``CsrfResponseMiddleware``). 202 1. A CSRF cookie that is set to a random value, which other sites will not have 203 access to. 79 204 80 2. On all incoming POST requests that have the session cookie set, it 81 checks that the 'csrfmiddlewaretoken' is present and correct. If it 82 isn't, the user will get a 403 error. (This is done by 83 ``CsrfViewMiddleware``) 205 This cookie is set by ``CsrfViewMiddleware``. 84 206 85 This ensures that only forms that have originated from your Web site 86 can be used to POST data back. 207 2. A hidden form field with the name 'csrfmiddlewaretoken' present in all 208 outgoing POST forms. The value of this field is the contents of the CSRF 209 cookie. 87 210 211 This part is done by the template tag (and with the legacy method, it is done 212 by ``CsrfResponseMiddleware``). 213 214 3. For all incoming POST requests that have the CSRF cookie set, the 215 'csrfmiddlewaretoken' must be present and correct. If it isn't, the user will 216 get a 403 error. 217 218 This check is done by ``CsrfViewMiddleware``. 219 220 This ensures that only forms that have originated from your Web site can be used 221 to POST data back. 222 88 223 It deliberately only targets HTTP POST requests (and the corresponding POST 89 forms). GET requests ought never to have any potentially dangerous side 90 effects (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a 91 CSRF attack with a GETrequest ought to be harmless.224 forms). GET requests ought never to have any potentially dangerous side effects 225 (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a CSRF attack with a GET 226 request ought to be harmless. 92 227 93 POST requests that are not accompanied by a session cookie are not protected, 94 but they do not need to be protected, since the 'attacking' Web site 95 could make these kind of requests anyway. 228 If the user has never visited the site before, and their browser makes a POST 229 request to the site, there will be no CSRF cookie, and no CSRF check will be 230 done. However, this is harmless, since if the user has never visited the site 231 before, they will not have any authentication that could be abused. 96 232 97 The Content-Type is checked before modifying the response, and only 98 pages that are served as 'text/html' or 'application/xml+xhtml' 99 are modified. 233 The Content-Type is checked before modifying the response, and only pages that 234 are served as 'text/html' or 'application/xml+xhtml' are modified. 100 235 101 236 The middleware tries to be smart about requests that come in via AJAX. Many 102 237 JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP header; … … 112 247 Limitations 113 248 =========== 114 249 115 CsrfMiddleware requires Django's session framework to work. If you have 116 a custom authentication system that manually sets cookies and the like, 117 it won't help you. 118 119 If your app creates HTML pages and forms in some unusual way, (e.g. 120 it sends fragments of HTML in JavaScript document.write statements) 121 you might bypass the filter that adds the hidden field to the form, 122 in which case form submission will always fail. It may still be possible 123 to use the middleware, provided you can find some way to get the 124 CSRF token and ensure that is included when your form is submitted. 250 If you are using ``CsrfResponseMiddleware`` and your app creates HTML pages and 251 forms in some unusual way, (e.g. it sends fragments of HTML in JavaScript 252 document.write statements) you might bypass the filter that adds the hidden 253 field to the form, in which case form submission will always fail. It may still 254 be possible to use this middleware, provided you use the template tag or 255 :meth:`django.contrib.csrf.middleware.get_token` to get the CSRF token and 256 ensure that is included when your form is submitted. -
docs/ref/settings.txt
144 144 The default number of seconds to cache a page when the caching middleware or 145 145 ``cache_page()`` decorator is used. 146 146 147 .. setting:: CSRF_COOKIE_NAME 148 149 CSRF_COOKIE_NAME 150 ---------------- 151 Default: ``'authid'`` 152 153 The name of the cookie to use for the CSRF authentication token. This can be whatever you 154 want. See :ref:`ref-contrib-csrf`. 155 156 .. setting:: CSRF_COOKIE_DOMAIN 157 158 CSRF_COOKIE_DOMAIN 159 --------------------- 160 161 Default: ``None`` 162 163 The domain to use for CSRF authentication cookies. Set this to a string such as 164 ``".example.com"`` for cross-domain cookies, or use ``None`` for a standard 165 domain cookie. See :ref:`ref-contrib-csrf`. 166 167 .. setting:: CSRF_FAILURE_VIEW 168 169 CSRF_FAILURE_VIEW 170 ----------------- 171 172 Default: ``'django.contrib.csrf.views.csrf_failure'`` 173 174 A dotted path to the view function to be used when an incoming request 175 is rejected by the CSRF protection. See :ref:`ref-contrib-csrf`. 176 147 177 .. setting:: DATABASE_ENGINE 148 178 149 179 DATABASE_ENGINE … … 762 792 763 793 ('django.middleware.common.CommonMiddleware', 764 794 'django.contrib.sessions.middleware.SessionMiddleware', 795 'django.contrib.csrf.middleware.CsrfViewMiddleware', 765 796 'django.contrib.auth.middleware.AuthenticationMiddleware',) 766 797 767 798 A tuple of middleware classes to use. See :ref:`topics-http-middleware`.