Ticket #9977: csrf_template_tag_18.diff
File csrf_template_tag_18.diff, 61.9 KB (added by , 16 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 # Dotted path to callable to be used as view when a request is 387 # rejected by the CSRF middleware. 388 CSRF_FAILURE_VIEW = 'django.contrib.csrf.views.csrf_failure' 389 390 # Some 'salt' to stop CSRF middleware being abused into generating and 391 # returning md5hash(SECRET_KEY + user supplied string). This probably 392 # is not needed with built-in session backends. It does not matter if 393 # this setting is not changed in individual settings files, because 394 # the SECRET_KEY is also used for hashing. 395 CSRF_SALT = 'g7x2(s0$h!^^_ykw81nm383yl58#@lpkfw_yv_yf' 396 380 397 ########### 381 398 # TESTING # 382 399 ########### -
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 10 try: 11 11 from functools import wraps 12 12 except ImportError: 13 13 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 14 14 15 15 from django.conf import settings 16 from django. http import HttpResponseForbidden16 from django.core.urlresolvers import get_callable 17 17 from django.utils.hashcompat import md5_constructor 18 18 from django.utils.safestring import mark_safe 19 19 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 20 _POST_FORM_RE = \ 23 21 re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) 24 22 25 23 _HTML_TYPES = ('text/html', 'application/xhtml+xml') 26 24 27 def _make_token(session_id): 28 return md5_constructor(settings.SECRET_KEY + session_id).hexdigest() 25 def _get_failure_view(): 26 """ 27 Returns the view to be used for CSRF rejections 28 """ 29 return get_callable(settings.CSRF_FAILURE_VIEW) 29 30 31 def _get_validated_session_id(request): 32 # This function is called by the csrf_token. So, we don't make the 33 # session framework a requirement, otherwise people would have to change 34 # their templates if they disabled the session middleware 35 if hasattr(request, 'session'): 36 if request.session.accessed or request.session.modified: 37 # Could be a new session, need to use new session ID 38 return request.session.session_key 39 else: 40 # Avoid use of session.session_key, which can trigger 41 # unecessary work 42 session_id = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None) 43 if session_id is not None and request.session.exists(session_id): 44 return session_id 45 else: 46 return None # not a valid session 47 return None 48 49 def get_token(request, salt=None): 50 """ 51 Returns the the CSRF token required for a session, 52 or None if there is no session active. 53 54 'salt' parameter is designed for internal use only. 55 """ 56 session_id = _get_validated_session_id(request) 57 if session_id is None: 58 # No session 59 return None 60 else: 61 return _make_token(session_id, salt=salt) 62 63 def _make_token(session_id, salt=None): 64 # 'salt' was added in case the session_id is not validated by the 65 # backend, which would create a potential vulnerability whereby an 66 # attacker could generate md5hash(SECRETE_KEY + arbitrary string), 67 # which could be useful to circumvent other protections. 68 if salt is None: 69 salt = settings.CSRF_SALT 70 71 return md5_constructor(settings.SECRET_KEY + salt + session_id).hexdigest() 72 30 73 class CsrfViewMiddleware(object): 31 74 """ 32 75 Middleware that requires a present and correct csrfmiddlewaretoken 33 76 for POST requests that have an active session. 77 78 This middleware should be used in conjunction with the csrf_token template 79 tag. 34 80 """ 35 81 def process_view(self, request, callback, callback_args, callback_kwargs): 36 82 if request.method == 'POST': … … 40 86 if request.is_ajax(): 41 87 return None 42 88 43 try: 44 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 45 except KeyError: 89 csrf_token = get_token(request) 90 if csrf_token is None: 91 # Coud happen if session middleware is disabled 92 assert hasattr(request, 'session'), "The CSRF middleware requires the session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to add 'django.contrib.sessions.middleware.SessionMiddleware'." 46 93 # No session, no check required 47 94 return None 48 95 49 csrf_token = _make_token(session_id)50 96 # check incoming token 51 97 try: 52 98 request_csrf_token = request.POST['csrfmiddlewaretoken'] 53 99 except KeyError: 54 return HttpResponseForbidden(_ERROR_MSG)100 return _get_failure_view()(request) 55 101 56 102 if request_csrf_token != csrf_token: 57 return HttpResponseForbidden(_ERROR_MSG) 103 # Earlier versions of Django did not use 'salt' in 104 # generating the token. On upgrading, a form 105 # generated by such a version will produce a 106 # different token, so to avoid upgrade bumps, we 107 # accept the old tokens 108 old_csrf_token = get_token(request, salt="") 109 if request_csrf_token != old_csrf_token: 110 return _get_failure_view()(request) 58 111 59 112 return None 60 113 … … 63 116 Middleware that post-processes a response to add a 64 117 csrfmiddlewaretoken if the response/request have an active 65 118 session. 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): … … 80 136 csrf_token = _make_token(cookie.value) 81 137 except KeyError: 82 138 # Normal case - look for existing session cookie 83 try:84 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]139 session_id = _get_validated_session_id(request) 140 if session_id is not None: 85 141 csrf_token = _make_token(session_id) 86 e xcept KeyError:142 else: 87 143 # no incoming or outgoing cookie 88 144 pass 89 145 90 146 if csrf_token is not None and \ 91 147 response['Content-Type'].split(';')[0] in _HTML_TYPES: 92 148 93 94 idattributes = itertools.chain(("id='csrfmiddlewaretoken'", ),95 149 # ensure we don't add the 'id' attribute twice (HTML validity) 150 idattributes = itertools.chain(("id='csrfmiddlewaretoken'", ), 151 itertools.repeat('')) 96 152 def add_csrf_field(match): 97 153 """Returns the matched <form> tag plus the added <input> element""" 98 154 return mark_safe(match.group() + "<div style='display:none;'>" + \ … … 109 165 Request Forgeries by adding hidden form fields to POST forms and 110 166 checking requests for the correct value. 111 167 112 In the list of middlewares, SessionMiddleware is required, and 113 must come after this middleware. CsrfMiddleWare must come after 114 compression middleware. 168 CsrfMiddleWare is composed of two middleware, CsrfViewMiddleware 169 and CsrfResponseMiddleware which can be used independently. 170 It is recommended to use only CsrfViewMiddleware and use the 171 csrf_token template tag in templates for inserting the token. 115 172 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.120 121 173 If you are setting cookies directly, instead of using Django's 122 174 session framework, this middleware will not work. 123 124 CsrfMiddleWare is composed of two middleware, CsrfViewMiddleware125 and CsrfResponseMiddleware which can be used independently.126 175 """ 127 176 pass 128 177 … … 132 181 from the post-processing of the CSRF middleware. 133 182 """ 134 183 def wrapped_view(*args, **kwargs): 135 resp = view_func( *args, **kwargs)184 resp = view_func( * args, ** kwargs) 136 185 resp.csrf_exempt = True 137 186 return resp 138 187 return wraps(view_func)(wrapped_view) … … 145 194 # are nicer if they don't have side-effects, so we return a new 146 195 # function. 147 196 def wrapped_view(*args, **kwargs): 148 return view_func( *args, **kwargs)197 return view_func( * args, ** kwargs) 149 198 wrapped_view.csrf_exempt = True 150 199 return wraps(view_func)(wrapped_view) 151 200 -
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>Cross Site Request Forgery detected. 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
Property changes on: django/contrib/csrf/views.py ___________________________________________________________________ Added: svn:eol-style + native
3 3 from django.test import TestCase 4 4 from django.http import HttpRequest, HttpResponse, HttpResponseForbidden 5 5 from django.contrib.csrf.middleware import CsrfMiddleware, _make_token, 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_view(request): 16 20 return post_form_response() 17 21 22 # Response/views used for template tag tests 23 def _token_template(): 24 return Template("{% load csrf %}{% csrf_token %}") 25 26 def _render_csrf_token_template(req): 27 context = RequestContext(req, processors=[csrf]) 28 template = _token_template() 29 return template.render(context) 30 31 def token_view(request): 32 return HttpResponse(_render_csrf_token_template(request)) 33 34 def token_view_with_session_access(request): 35 request.session["test value"] = "value" 36 return HttpResponse(_render_csrf_token_template(request)) 37 38 def token_view_with_late_session_access(request): 39 # This view creates RequestContext and *then* accesses the 40 # session. This will be problematic unless the csrf context 41 # processor is lazy. 42 assert not (request.session.accessed or request.session.modified) 43 context = RequestContext(request, processors=[csrf]) 44 request.session["test value"] = "value" 45 assert (request.session.accessed or request.session.modified) 46 template = _token_template() 47 return HttpResponse(template.render(context)) 48 49 def token_view_with_new_session(request): 50 # View deliberately cycles the session key 51 request.session.create() 52 return HttpResponse(_render_csrf_token_template(request)) 53 18 54 class CsrfMiddlewareTest(TestCase): 19 55 20 _session_id = "1" 56 def setUp(self, *args, **kwargs): 57 super(CsrfMiddlewareTest, self).setUp(*args, **kwargs) 58 # We have to create an actual session in the DB as the 59 # middleware validates the session 60 engine = import_module(settings.SESSION_ENGINE) 61 s = engine.SessionStore(None) 62 s.create() 63 self._session_id = s.session_key 21 64 65 def _apply_request_middleware(self, req): 66 SessionMiddleware().process_request(req) 67 return req 68 22 69 def _get_GET_no_session_request(self): 23 return HttpRequest()70 return self._apply_request_middleware(HttpRequest()) 24 71 25 72 def _get_GET_session_request(self): 26 req = self._get_GET_no_session_request()73 req = HttpRequest() 27 74 req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id 28 return req75 return self._apply_request_middleware(req) 29 76 30 77 def _get_POST_session_request(self): 31 req = self._get_GET_session_request() 78 req = HttpRequest() 79 req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id 32 80 req.method = "POST" 33 return req81 return self._apply_request_middleware(req) 34 82 35 83 def _get_POST_no_session_request(self): 36 req = self._get_GET_no_session_request()84 req = HttpRequest() 37 85 req.method = "POST" 38 return req86 return self._apply_request_middleware(req) 39 87 40 88 def _get_POST_session_request_with_token(self): 41 89 req = self._get_POST_session_request() 42 90 req.POST['csrfmiddlewaretoken'] = _make_token(self._session_id) 43 91 return req 44 92 45 def _get_post_form_response(self):46 return post_form_response()47 48 93 def _get_new_session_response(self): 49 resp = self._get_post_form_response()94 resp = post_form_response() 50 95 resp.cookies[settings.SESSION_COOKIE_NAME] = self._session_id 51 96 return resp 52 97 53 98 def _check_token_present(self, response): 54 99 self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % _make_token(self._session_id)) 55 100 56 def get_view(self):57 return test_view58 59 101 # Check the post processing 60 102 def test_process_response_no_session(self): 61 103 """ 62 104 Check the the post-processor does nothing if no session active 63 105 """ 64 106 req = self._get_GET_no_session_request() 65 resp = self._get_post_form_response()107 resp = post_form_response() 66 108 resp_content = resp.content # needed because process_response modifies resp 67 109 resp2 = CsrfMiddleware().process_response(req, resp) 68 110 self.assertEquals(resp_content, resp2.content) … … 72 114 Check that the token is inserted if there is an existing session 73 115 """ 74 116 req = self._get_GET_session_request() 75 resp = self._get_post_form_response()117 resp = post_form_response() 76 118 resp_content = resp.content # needed because process_response modifies resp 77 119 resp2 = CsrfMiddleware().process_response(req, resp) 78 120 self.assertNotEqual(resp_content, resp2.content) … … 94 136 Check that no post processing is done for an exempt view 95 137 """ 96 138 req = self._get_POST_session_request() 97 resp = csrf_exempt( self.get_view())(req)139 resp = csrf_exempt(post_form_view)(req) 98 140 resp_content = resp.content 99 141 resp2 = CsrfMiddleware().process_response(req, resp) 100 142 self.assertEquals(resp_content, resp2.content) … … 106 148 to the incoming request. 107 149 """ 108 150 req = self._get_POST_no_session_request() 109 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})151 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 110 152 self.assertEquals(None, req2) 111 153 112 154 def test_process_request_session_no_token(self): … … 114 156 Check that if a session is present but no token, we get a 'forbidden' 115 157 """ 116 158 req = self._get_POST_session_request() 117 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})159 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 118 160 self.assertEquals(HttpResponseForbidden, req2.__class__) 119 161 120 162 def test_process_request_session_and_token(self): … … 122 164 Check that if a session is present and a token, the middleware lets it through 123 165 """ 124 166 req = self._get_POST_session_request_with_token() 125 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})167 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 126 168 self.assertEquals(None, req2) 127 169 170 def test_process_request_old_token_compat(self): 171 """ 172 Check that the view middleware accepts tokens generated by 173 previous version of response middleware. 174 """ 175 req = self._get_POST_session_request_with_token() 176 # Previous versions did not use 'salt' in _make_token 177 req.POST['csrfmiddlewaretoken'] = _make_token(self._session_id, salt="") 178 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 179 self.assertEquals(None, req2) 180 128 181 def test_process_request_session_no_token_exempt_view(self): 129 182 """ 130 183 Check that if a session is present and no token, but the csrf_exempt 131 184 decorator has been applied to the view, the middleware lets it through 132 185 """ 133 186 req = self._get_POST_session_request() 134 req2 = CsrfMiddleware().process_view(req, csrf_exempt( self.get_view()), (), {})187 req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {}) 135 188 self.assertEquals(None, req2) 136 189 137 190 def test_ajax_exemption(self): … … 140 193 """ 141 194 req = self._get_POST_session_request() 142 195 req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' 143 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})196 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 144 197 self.assertEquals(None, req2) 198 199 # Tests for the template tag method 200 def test_token_node_no_session(self): 201 """ 202 Check that CsrfTokenNode works when no session is active 203 """ 204 req = self._get_GET_no_session_request() 205 resp = token_view(req) 206 self.assertEquals(u"", resp.content) 207 208 def test_token_node_with_session(self): 209 """ 210 Check that CsrfTokenNode works when a session is active 211 """ 212 req = self._get_GET_session_request() 213 resp = token_view(req) 214 self._check_token_present(resp) 215 216 def test_token_node_with_new_session(self): 217 """ 218 Check that CsrfTokenNode works when a session is created by 219 the view (when one was not already active) 220 """ 221 req = self._get_GET_no_session_request() 222 resp = token_view_with_session_access(req) 223 # view will have caused new session to be created 224 self._session_id = req.session.session_key 225 self._check_token_present(resp) 226 227 def test_token_node_with_changed_session(self): 228 """ 229 Check that CsrfTokenNode works when a session is deliberately 230 created by the view (though one was already active) 231 """ 232 req = self._get_GET_session_request() 233 resp = token_view_with_new_session(req) 234 # View will have modified session key 235 self._session_id = req.session.session_key 236 self._check_token_present(resp) 237 238 def test_token_node_with_modified_session_data(self): 239 """ 240 Check that CsrfTokenNode works when session data is modified 241 by the view 242 """ 243 req = self._get_GET_session_request() 244 resp = token_view_with_session_access(req) 245 # View should not have modified session key 246 self._check_token_present(resp) 247 248 def test_token_node_with_late_session_access(self): 249 """ 250 Check that CsrfTokenNode works when a session is created by 251 the view *after* the RequestContext has been created 252 """ 253 req = self._get_GET_no_session_request() 254 resp = token_view_with_late_session_access(req) 255 # view will have caused new session to be created 256 self._session_id = req.session.session_key 257 self._check_token_present(resp) 258 -
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
Property changes on: django/contrib/csrf/templatetags/csrf.py ___________________________________________________________________ Added: svn:eol-style + native
1 -
django/contrib/csrf/context_processors.py
Property changes on: django/contrib/csrf/templatetags/__init__.py ___________________________________________________________________ Added: svn:eol-style + native
1 from django.contrib.csrf.middleware import get_token 2 from django.utils.functional import lazy, 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 an empty dict. 15 return 'NOTNEEDED' 16 else: 17 return token 18 # We need to generate the value as late as possible, in case the 19 # user creates RequestContext early in the view. But we also want 20 # to memoize so that we don't call this many times. 21 cache = {} 22 _get_val = lazy(memoize(_get_val, cache, 0), str) 23 24 return {'csrf_token': _get_val() } -
django/contrib/auth/views.py
Property changes on: django/contrib/csrf/context_processors.py ___________________________________________________________________ Added: svn:eol-style + native
137 137 else: 138 138 context_instance['validlink'] = False 139 139 form = None 140 context_instance['form'] = form 140 context_instance['form'] = form 141 141 return render_to_response(template_name, context_instance=context_instance) 142 142 143 143 def password_reset_complete(request, template_name='registration/password_reset_complete.html'): -
django/contrib/auth/tests/views.py
53 53 # Let's munge the token in the path, but keep the same length, 54 54 # in case the URLconf will reject a different length. 55 55 path = path[:-5] + ("0"*4) + path[-1] 56 57 56 response = self.client.get(path) 58 57 self.assertEquals(response.status_code, 200) 59 58 self.assert_("The password reset link was invalid" in response.content) -
tests/regressiontests/admin_views/tests.py
803 803 # 4 action inputs (3 regular checkboxes, 1 checkbox to select all) 804 804 # main form submit button = 1 805 805 # search field and search submit button = 2 806 # 6 + 2 + 1 + 2 = 11 inputs 807 self.failUnlessEqual(response.content.count("<input"), 15) 806 # csrf hidden field = 1 807 # 6 + 2 + 4 + 1 + 2 + 1 = 16 inputs 808 self.failUnlessEqual(response.content.count("<input"), 16) 808 809 # 1 select per object = 3 selects 809 810 self.failUnlessEqual(response.content.count("<select"), 4) 810 811 -
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(): -
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`. (Currently it can 40 come anywhere in the list with respect to other middleware included in 41 Django. It should come before any view middleware that assume that CSRF 42 attacks have been dealt with.) 41 43 44 2. Add ``'django.contrib.csrf'`` to your :setting:`INSTALLED_APPS`. 45 46 3. In any template that uses a POST form, first load the 'csrf' template tag 47 library:: 48 49 {% load csrf %} 50 51 Then use the ``csrf_token`` tag inside the ``<form>`` element, e.g.:: 52 53 <form action="" method="POST">{% csrf_token %} 54 55 4. In the corresponding view functions, ensure that the 56 ``'django.contrib.csrf.context_processors.csrf'`` is being used. Usually, 57 this can be done in one of two ways: 58 59 1. Using RequestContext: 60 61 1. Ensure ``'django.contrib.csrf.context_processors.csrf'`` is present 62 in your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. It is 63 present by default. 64 65 2. Use ``RequestContext`` as the context instance in the relevant 66 views. If you are using generic views or contrib apps, you are 67 covered already. 68 69 2. Manually import and use the processor to generate the CSRF token and 70 add it to the template context. e.g.:: 71 72 from django.contrib.csrf.context_processors import csrf 73 from django.template import Context 74 from django.shortcuts import render_to_response 75 def my_view(request): 76 c = Context() 77 c.update(csrf(request)) 78 return render_to_response("a_template.html", context_instance=c) 79 80 5. Ensure that any code in a view which could create a new session executes 81 **before** any templates containing a ``csrf_token`` tag are 82 rendered. Note that sessions can be created implicitly simply by setting 83 a value or accessing the contents. If this is done after the template is 84 rendered, the CSRF token it contains could be incorrect, and the 85 following form submission will be rejected. 86 87 Legacy method 88 ------------- 89 90 In Django 1.0, the template tag did not exist. Instead, a post-processing 91 middleware that re-wrote POST forms to include the CRSF token was used. If you 92 are upgrading a site from version 1.0 or earlier, please read this section and 93 the `Upgrading notes`_ below. The post-processing middleware is still available 94 as ``CsrfResponseMiddleware``, and it can be used by following these steps: 95 96 1. Follow step 1 above to install ``CsrfViewMiddleware``. 97 98 2. Add ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'`` to your 99 :setting:`MIDDLEWARE_CLASSES` setting. 100 101 ``CsrfResponseMiddleware`` needs to process the response after the 102 ``SessionMiddleware``, so must come before it in the list. It also must 103 process the response before things like compression happen to the 104 response, so it must come after ``GZipMiddleware`` in the list. 105 106 Use of the ``CsrfResponseMiddleware`` is not recommended, but it can be used as 107 an interim measure until applications have been updated to use the ``{% 108 crsf_token %}`` tag. 109 110 Django 1.0 provided a single ``CsrfMiddleware`` class. This is also still 111 available for backwards compatibility. It combines the functions of the two new 112 middleware. 113 114 Upgrading notes 115 --------------- 116 117 When upgrading to version 1.1 or later, you may have applications that rely on 118 the old post-processing functionality for CSRF protection, or you may not have 119 enabled any CSRF protection. This section outlines the steps necessary for a 120 smooth upgrade, without having to fix all the applications to use the new 121 template tag method immediately. 122 123 If you are using any of the contrib apps (such as the admin), there are some 124 required steps for these applications to continue working. First, the CSRF 125 application must be added to :setting:`INSTALLED_APPS` (See `How to use it`_ 126 above, step 2). Second, the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting must 127 be updated (step 4.1.1 above). 128 129 If you have ``CsrfMiddleware`` in your :setting:`MIDDLEWARE_CLASSES`, you will now 130 have a working installation with CSRF protection. It is recommended at this 131 point that you replace ``CsrfMiddleware`` with its two components, 132 ``CsrfViewMiddleware`` and ``CsrfResponseMiddleware``. 133 134 If you do not have any of the the middleware in your :setting:`MIDDLEWARE_CLASSES`, 135 you will have a working installation but without any CSRF protection (just as 136 you had before). It is recommended to install ``CsrfViewMiddleware`` and 137 ``CsrfResponseMiddleware``, but if you are not interested in having any CSRF 138 protection, you can simply stop here. 139 140 Assuming you have followed the above, all views in your Django site will now be 141 protected by the ``CsrfViewMiddleware``. Contrib apps meet the requirements 142 imposed by the ``CsrfViewMiddleware`` using the template tag, and other 143 applications in your project will meet its requirements by virtue of the 144 ``CsrfResponseMiddleware``. 145 146 The next step is to update all your applications to use the template tag, as 147 described in `How to use it`_, steps 3-5. This can be done as soon as is 148 practical. Any applications that are updated will now require Django 1.1 or 149 later, since they will use the CSRF template tag library which was not available 150 in earlier versions. 151 152 Finally, once all applications are upgraded, the ``CsrfResponseMiddleware`` can 153 be removed. 154 155 While in the process of upgrading, the ``csrf_response_exempt`` decorator, 156 described in `Exceptions`_, may be useful. The post-processing middleware 157 imposes a performance hit, and any views that have been upgraded to use the new 158 template tag method no longer need it. Using this decorator will allow you to 159 avoid this performance hit. 160 42 161 Exceptions 43 162 ---------- 44 163 45 164 .. versionadded:: 1.1 46 165 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::166 To manually exclude a view function from being handled by either of the two CSRF 167 middleware, you can use the ``csrf_exempt`` decorator, found in the 168 ``django.contrib.csrf.middleware`` module. For example:: 50 169 51 170 from django.contrib.csrf.middleware import csrf_exempt 52 171 … … 54 173 return HttpResponse('Hello world') 55 174 my_view = csrf_exempt(my_view) 56 175 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.176 Like the middleware, the ``csrf_exempt`` decorator is composed of two parts: a 177 ``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` decorator, found 178 in the same module. These disable the view protection mechanism 179 (``CsrfViewMiddleware``) and the response post-processing 180 (``CsrfResponseMiddleware``) respectively. They can be used individually if 181 required. 63 182 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.)183 You don't have to worry about doing this for most AJAX views. Any request sent 184 with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the next 185 section.) 67 186 187 Rejected requests 188 ================= 189 190 By default, a '403 Forbidden' response is sent to the user if an incoming 191 request fails the checks performed by ``CsrfViewMiddleware``. This should 192 usually only be seen when there is a genuine Cross Site Request Forgery, or 193 when, due to a programming error, the CSRF token has not been included with a 194 POST form. 195 196 No logging is done, and the error message is not very friendly, so you may want 197 to provide your own page for handling this condition. To do this, simply set 198 the :setting:`CSRF_FAILURE_VIEW` setting to a dotted path to your own view 199 function. 200 68 201 How it works 69 202 ============ 70 203 71 CsrfMiddleware does two things:204 The CSRF protection requires two things: 72 205 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``). 206 1. A hidden form field with the name 'csrfmiddlewaretoken' must be added to all 207 outgoing POST forms. The value of this field is a hash of the session ID 208 plus a secret. If there is no session ID set, this modification of the 209 response isn't done, so there is very little performance penalty for those 210 requests that don't have a session. 79 211 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``) 212 This part is done by the template tag (and with the legacy method, it is done 213 by ``CsrfResponseMiddleware``). 84 214 85 This ensures that only forms that have originated from your Web site 86 can be used to POST data back. 215 2. On all incoming POST requests that have the session cookie set, the 216 'csrfmiddlewaretoken' must be present and correct. If it isn't, the user will 217 get a 403 error. 87 218 219 This check is done by ``CsrfViewMiddleware``. 220 221 This ensures that only forms that have originated from your Web site can be used 222 to POST data back. 223 88 224 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.225 forms). GET requests ought never to have any potentially dangerous side effects 226 (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a CSRF attack with a GET 227 request ought to be harmless. 92 228 93 229 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 makethese kind of requests anyway.230 but they do not need to be protected, since the 'attacking' Web site could make 231 these kind of requests anyway. 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'thelp you.250 These middleware require Django's session framework to work. If you have a 251 custom authentication system that manually sets cookies and the like, it won't 252 help you. 118 253 119 If you r 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 the254 If you are using ``CsrfResponseMiddleware`` and your app creates HTML pages and 255 forms in some unusual way, (e.g. it sends fragments of HTML in JavaScript 256 document.write statements) you might bypass the filter that adds the hidden 257 field to the form, in which case form submission will always fail. It may still 258 be possible to use the middleware, provided you can find some way to get the 124 259 CSRF token and ensure that is included when your form is submitted. -
docs/ref/settings.txt
146 146 147 147 .. setting:: DATABASE_ENGINE 148 148 149 CSRF_FAILURE_VIEW 150 ----------------- 151 152 Default: ``'django.contrib.csrf.views.csrf_failure'`` 153 154 The name of the view function to be used when an incoming request 155 is rejected by the CSRF protection. See :ref:`ref-contrib-csrf`. 156 157 CSRF_SALT 158 --------- 159 160 Some additional 'salt' used by the CSRF middleware when hashing, to 161 avoid a potential security problem. Does not need to be changed. See 162 source for more details. 163 149 164 DATABASE_ENGINE 150 165 --------------- 151 166 … … 762 777 763 778 ('django.middleware.common.CommonMiddleware', 764 779 'django.contrib.sessions.middleware.SessionMiddleware', 780 'django.contrib.csrf.middleware.CsrfViewMiddleware', 765 781 'django.contrib.auth.middleware.AuthenticationMiddleware',) 766 782 767 783 A tuple of middleware classes to use. See :ref:`topics-http-middleware`.