Ticket #9977: csrf_template_tag_14.diff
File csrf_template_tag_14.diff, 50.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 <input type="hidden" name="next" value="{{ next }}" id="next" /> 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 form.errors %} 10 10 <h1>{% blocktrans count form.errors|length as counter %}Please correct the error below{% plural %}Please correct the errors below{% endblocktrans %}</h1> 11 11 {% else %} -
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 <input type="hidden" name="next" value="{{ next }}" id="next" /> 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 {% for field in form %} 4 4 {% if field.is_hidden %} 5 5 {{ field }} -
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 <input type="hidden" name="next" value="{{ next }}" id="next" /> 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/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/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 }} … … 63 63 {% endif %} 64 64 {% endblock %} 65 65 66 <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}> 66 <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %} 67 67 {% if cl.formset %} 68 68 {{ cl.formset.management_form }} 69 69 {% endif %} -
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 %} … … 14 14 </div> 15 15 {% endif %}{% endblock %} 16 16 {% block content %}<div id="content-main"> 17 <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}17 <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %} 18 18 <div> 19 19 {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} 20 20 {% 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/csrf/middleware.py
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 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) 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 required, so that people can disable the 34 # session middleware without having to change their templates. 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): 50 """ 51 Returns the the CSRF token required for a session, 52 or None if there is no session active. 53 """ 54 session_id = _get_validated_session_id(request) 55 if session_id is None: 56 # No session 57 return None 58 else: 59 return _make_token(session_id) 60 27 61 def _make_token(session_id): 28 return md5_constructor(settings.SECRET_KEY + se ssion_id).hexdigest()62 return md5_constructor(settings.SECRET_KEY + settings.CSRF_SALT + session_id).hexdigest() 29 63 30 64 class CsrfViewMiddleware(object): 31 65 """ … … 40 74 if request.is_ajax(): 41 75 return None 42 76 43 try: 44 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] 45 except KeyError: 77 csrf_token = get_token(request) 78 if csrf_token is None: 79 # Coud happen if session middleware is disabled 80 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 81 # No session, no check required 47 82 return None 48 83 49 csrf_token = _make_token(session_id)50 84 # check incoming token 51 85 try: 52 86 request_csrf_token = request.POST['csrfmiddlewaretoken'] 53 87 except KeyError: 54 return HttpResponseForbidden(_ERROR_MSG)88 return _get_failure_view()(request) 55 89 56 90 if request_csrf_token != csrf_token: 57 return HttpResponseForbidden(_ERROR_MSG)91 return _get_failure_view()(request) 58 92 59 93 return None 60 94 … … 80 114 csrf_token = _make_token(cookie.value) 81 115 except KeyError: 82 116 # Normal case - look for existing session cookie 83 try:84 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]117 session_id = _get_validated_session_id(request) 118 if session_id is not None: 85 119 csrf_token = _make_token(session_id) 86 e xcept KeyError:120 else: 87 121 # no incoming or outgoing cookie 88 122 pass 89 123 -
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 128 170 def test_process_request_session_no_token_exempt_view(self): … … 131 173 decorator has been applied to the view, the middleware lets it through 132 174 """ 133 175 req = self._get_POST_session_request() 134 req2 = CsrfMiddleware().process_view(req, csrf_exempt( self.get_view()), (), {})176 req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {}) 135 177 self.assertEquals(None, req2) 136 178 137 179 def test_ajax_exemption(self): … … 140 182 """ 141 183 req = self._get_POST_session_request() 142 184 req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' 143 req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})185 req2 = CsrfMiddleware().process_view(req, post_form_view, (), {}) 144 186 self.assertEquals(None, req2) 187 188 # Tests for the template tag method 189 def test_token_node_no_session(self): 190 """ 191 Check that CsrfTokenNode works when no session is active 192 """ 193 req = self._get_GET_no_session_request() 194 resp = token_view(req) 195 self.assertEquals(u"", resp.content) 196 197 def test_token_node_with_session(self): 198 """ 199 Check that CsrfTokenNode works when a session is active 200 """ 201 req = self._get_GET_session_request() 202 resp = token_view(req) 203 self._check_token_present(resp) 204 205 def test_token_node_with_new_session(self): 206 """ 207 Check that CsrfTokenNode works when a session is created by 208 the view (when one was not already active) 209 """ 210 req = self._get_GET_no_session_request() 211 resp = token_view_with_session_access(req) 212 # view will have caused new session to be created 213 self._session_id = req.session.session_key 214 self._check_token_present(resp) 215 216 def test_token_node_with_changed_session(self): 217 """ 218 Check that CsrfTokenNode works when a session is deliberately 219 created by the view (though one was already active) 220 """ 221 req = self._get_GET_session_request() 222 resp = token_view_with_new_session(req) 223 # View will have modified session key 224 self._session_id = req.session.session_key 225 self._check_token_present(resp) 226 227 def test_token_node_with_modified_session_data(self): 228 """ 229 Check that CsrfTokenNode works when session data is modified 230 by the view 231 """ 232 req = self._get_GET_session_request() 233 resp = token_view_with_session_access(req) 234 # View should not have modified session key 235 self._check_token_present(resp) 236 237 def test_token_node_with_late_session_access(self): 238 """ 239 Check that CsrfTokenNode works when a session is created by 240 the view *after* the RequestContext has been created 241 """ 242 req = self._get_GET_no_session_request() 243 resp = token_view_with_late_session_access(req) 244 # view will have caused new session to be created 245 self._session_id = req.session.session_key 246 self._check_token_present(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/context_processors.py
Property changes on: django/contrib/csrf/templatetags/csrf.py ___________________________________________________________________ Added: svn:eol-style + native 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
130 130 else: 131 131 context_instance['validlink'] = False 132 132 form = None 133 context_instance['form'] = form 133 context_instance['form'] = form 134 134 return render_to_response(template_name, context_instance=context_instance) 135 135 136 136 def password_reset_complete(request, template_name='registration/password_reset_complete.html'): -
django/contrib/auth/tests/views.py
50 50 # Lets munge the token in the path, but keep the same length, 51 51 # in case the URL conf will reject a different length 52 52 path = path[:-5] + ("0"*4) + path[-1] 53 54 53 response = self.client.get(path) 55 54 self.assertEquals(response.status_code, 200) 56 55 self.assert_("The password reset link was invalid" in response.content) -
tests/regressiontests/admin_views/tests.py
747 747 # 4 action inputs (3 regular checkboxes, 1 checkbox to select all) 748 748 # main form submit button = 1 749 749 # search field and search submit button = 2 750 # 6 + 2 + 1 + 2 = 11 inputs 751 self.failUnlessEqual(response.content.count("<input"), 15) 750 # csrf hidden field = 1 751 # 6 + 2 + 4 + 1 + 2 + 1 = 16 inputs 752 self.failUnlessEqual(response.content.count("<input"), 16) 752 753 # 1 select per object = 3 selects 753 754 self.failUnlessEqual(response.content.count("<select"), 4) 754 755 -
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 CsrfMiddleware class provides easy-to-use protection against 11 `Cross Site Request Forgeries`_. This type of attack occurs when a malicious 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 into clicking on the link in their browser. 10 The CSRF middleware and template tag provides easy-to-use protection 11 against `Cross Site Request Forgeries`_. This type of attack occurs 12 when a malicious Web site creates a link or form button that is 13 intended to perform some action on your Web site, using the 14 credentials of a logged-in user who is tricked into clicking on the 15 link in their browser. 15 16 16 17 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. 18 are side-effect free. POST requests can then be protected by adding 19 these middleware into your list of installed middleware following the 20 steps below. 19 21 22 .. versionadded:: 1.1 23 The functionality described here is depended on by the 'contrib' 24 apps, including the admin, so usage steps 1, 2 and 4.1.1 below are 25 **required** for these apps to function. 26 20 27 .. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF 21 28 22 29 How to use it 23 30 ============= 31 .. versionchanged:: 1.1 32 The template tag functionality (the recommended way to use this) 33 was added in version 1.1. The previous method (still available) is 34 described under 'Legacy method'. 24 35 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. 36 To enable CSRF protection for your views, follow these steps: 31 37 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``. 38 1. Add the middleware 39 ``'django.contrib.csrf.middleware.CsrfViewMiddleware'`` to your 40 list of middleware classes, :setting:`MIDDLEWARE_CLASSES`. 41 (Currently it can come anywhere in the list with respect to 42 other middleware included in Django. It should come before any 43 view middleware that assume that CSRF attacks have been dealt 44 with.) 37 45 38 .. versionchanged:: 1.1 39 (previous versions of Django did not provide these two components 40 of ``CsrfMiddleware`` as described above) 46 2. Add ``'django.contrib.csrf'`` to your :setting:`INSTALLED_APPS`. 41 47 48 3. In any template that uses a POST form, first load the 'csrf' 49 template tag library:: 50 51 {% load csrf %} 52 53 Then use the ``csrf_token`` tag inside the ``<form>`` element, e.g.:: 54 55 <form action="" method="POST">{% csrf_token %} 56 57 4. In the corresponding view functions, ensure that the 58 ``'django.contrib.csrf.context_processors.csrf'`` is being 59 used. Usually, this can be done in one of two ways: 60 61 1. Using RequestContext: 62 63 1. Ensure ``'django.contrib.csrf.context_processors.csrf'`` 64 is present in your :setting:`TEMPLATE_CONTEXT_PROCESSORS` 65 setting. It is present by default. 66 67 2. Use ``RequestContext`` as the context instance in the 68 relevant views. If you are using generic views or contrib 69 apps, you are covered already. 70 71 2. Manually import and use the processor to generate the CSRF 72 token and add it to the template context. e.g.:: 73 74 from django.contrib.csrf.context_processors import csrf 75 from django.template import Context 76 from django.shortcuts import render_to_response 77 def my_view(request): 78 c = Context() 79 c.update(csrf(request)) 80 return render_to_response("a_template.html", context_instance=c) 81 82 5. Ensure that any code in a view which could create a new session 83 executes **before** any templates containing a ``csrf_token`` 84 tag is rendered. Note that sessions can be created implicitly 85 simply by setting a value or accessing the contents. If this 86 is done after the template is rendered, the CSRF token it 87 contains could be incorrect, and the following form submission 88 will be rejected. 89 90 Legacy method 91 ------------- 92 93 In Django 1.0, the template tag did not exist. Instead, a 94 post-processing middleware that re-wrote POST forms to include the 95 CRSF token was used. This is still available as 96 ``CsrfResponseMiddleware``, and it can be used by following these 97 steps: 98 99 1. Follow step 1 above to install ``CsrfViewMiddleware``. 100 101 2. Add ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'`` 102 to your :setting:`MIDDLEWARE_CLASSES` setting. 103 104 ``CsrfResponseMiddleware`` needs to process the response after 105 the ``SessionMiddleware``, so must come before it in the list. 106 It also must process the response before things like 107 compression happen to the response, so it must come after 108 ``GZipMiddleware`` in the list. 109 110 Use of the ``CsrfResponseMiddleware`` is not recommended, but it can 111 be used as an interim measure until applications have been updated to use 112 the ``{% crsf_token %}`` tag. 113 114 Django 1.0 provided a single ``CsrfMiddleware`` class. This is also 115 still available for backwards compatibility. It combines the 116 functions of the two new middleware. 117 118 42 119 Exceptions 43 120 ---------- 44 121 45 122 .. versionadded:: 1.1 46 123 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::124 To manually exclude a view function from being handled by either of 125 the two CSRF middleware, you can use the ``csrf_exempt`` decorator, 126 found in the ``django.contrib.csrf.middleware`` module. For example:: 50 127 51 128 from django.contrib.csrf.middleware import csrf_exempt 52 129 … … 54 131 return HttpResponse('Hello world') 55 132 my_view = csrf_exempt(my_view) 56 133 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 the61 response post-processing (``CsrfResponseMiddleware``) respectively. 62 They canbe used individually if required.134 Like the middleware, the ``csrf_exempt`` decorator is composed of two 135 parts: a ``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` 136 decorator, found in the same module. These disable the view 137 protection mechanism (``CsrfViewMiddleware``) and the response 138 post-processing (``CsrfResponseMiddleware``) respectively. They can 139 be used individually if required. 63 140 64 141 You don't have to worry about doing this for most AJAX views. Any 65 142 request sent with "X-Requested-With: XMLHttpRequest" is automatically 66 143 exempt. (See the next section.) 67 144 145 Rejected requests 146 ================= 147 148 By default, a '403 Forbidden' response is sent to the user if an 149 incoming request fails the checks performed by ``CsrfViewMiddleware``. 150 This should usually only be seen when there is a genuine Cross Site 151 Request Forgery, or when, due to a programming error, the CSRF token 152 has not been included with a POST form. 153 154 No logging is done, and the error message is not very friendly, so you 155 may want to provide your own page for handling this condition. To do 156 this, simply set the :setting:`CSRF_FAILURE_VIEW` setting to a dotted 157 path to your own view function. 158 68 159 How it works 69 160 ============ 70 161 71 CsrfMiddleware does two things:162 The CSRF protection requires two things: 72 163 73 1. It modifies outgoing requests by adding a hidden form field to all74 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is75 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 little77 performance penalty for those requests that don't have a session.78 (This is done by ``CsrfResponseMiddleware``).164 1. A hidden form field with the name 'csrfmiddlewaretoken' must be 165 added to all outgoing POST forms. The value of this field is a 166 hash of the session ID plus a secret. If there is no session ID 167 set, this modification of the response isn't done, so there is very 168 little performance penalty for those requests that don't have a 169 session. 79 170 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``) 171 This part is done by the template tag (and with the 172 legacy method, it is done by ``CsrfResponseMiddleware``). 84 173 174 2. On all incoming POST requests that have the session cookie set, the 175 'csrfmiddlewaretoken' must be present and correct. If it isn't, the 176 user will get a 403 error. 177 178 This check is done by ``CsrfViewMiddleware``. 179 85 180 This ensures that only forms that have originated from your Web site 86 181 can be used to POST data back. 87 182 … … 112 207 Limitations 113 208 =========== 114 209 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.210 These middleware require Django's session framework to work. If you 211 have a custom authentication system that manually sets cookies and the 212 like, it won't help you. 118 213 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. 214 If you are using ``CsrfResponseMiddleware`` and your app creates HTML 215 pages and forms in some unusual way, (e.g. it sends fragments of HTML 216 in JavaScript document.write statements) you might bypass the filter 217 that adds the hidden field to the form, in which case form submission 218 will always fail. It may still be possible to use the middleware, 219 provided you can find some way to get the CSRF token and ensure that 220 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`.