+50
-51
lines changedFilter options
+50
-51
lines changed Original file line number Diff line number Diff line change
@@ -97,6 +97,7 @@ def _reject(self, request, reason):
97
97
return _get_failure_view()(request, reason=reason)
98
98
99
99
def process_view(self, request, callback, callback_args, callback_kwargs):
100
+
100
101
if getattr(request, 'csrf_processing_done', False):
101
102
return None
102
103
@@ -130,31 +131,6 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
130
131
# any branches that call reject()
131
132
return self._accept(request)
132
133
133
-
if request.is_ajax():
134
-
# .is_ajax() is based on the presence of X-Requested-With. In
135
-
# the context of a browser, this can only be sent if using
136
-
# XmlHttpRequest. Browsers implement careful policies for
137
-
# XmlHttpRequest:
138
-
#
139
-
# * Normally, only same-domain requests are allowed.
140
-
#
141
-
# * Some browsers (e.g. Firefox 3.5 and later) relax this
142
-
# carefully:
143
-
#
144
-
# * if it is a 'simple' GET or POST request (which can
145
-
# include no custom headers), it is allowed to be cross
146
-
# domain. These requests will not be recognized as AJAX.
147
-
#
148
-
# * if a 'preflight' check with the server confirms that the
149
-
# server is expecting and allows the request, cross domain
150
-
# requests even with custom headers are allowed. These
151
-
# requests will be recognized as AJAX, but can only get
152
-
# through when the developer has specifically opted in to
153
-
# allowing the cross-domain POST request.
154
-
#
155
-
# So in all cases, it is safe to allow these requests through.
156
-
return self._accept(request)
157
-
158
134
if request.is_secure():
159
135
# Strict referer checking for HTTPS
160
136
referer = request.META.get('HTTP_REFERER')
@@ -185,7 +161,11 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
185
161
csrf_token = request.META["CSRF_COOKIE"]
186
162
187
163
# check incoming token
188
-
request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
164
+
request_csrf_token = request.POST.get('csrfmiddlewaretoken', "")
165
+
if request_csrf_token == "":
166
+
# Fall back to X-CSRFToken, to make things easier for AJAX
167
+
request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
168
+
189
169
if request_csrf_token != csrf_token:
190
170
if cookie_is_new:
191
171
# probably a problem setting the CSRF cookie
Original file line number Diff line number Diff line change
@@ -81,6 +81,47 @@ The utility script ``extras/csrf_migration_helper.py`` can help to automate the
81
81
finding of code and templates that may need to be upgraded. It contains full
82
82
help on how to use it.
83
83
84
+
AJAX
85
+
----
86
+
87
+
While the above method can be used for AJAX POST requests, it has some
88
+
inconveniences: you have to remember to pass the CSRF token in as POST data with
89
+
every POST request. For this reason, there is an alternative method: on each
90
+
XMLHttpRequest, set a custom `X-CSRFToken` header to the value of the CSRF
91
+
token. This is often easier, because many javascript frameworks provide hooks
92
+
that allow headers to be set on every request. In jQuery, you can use the
93
+
``beforeSend`` hook as follows:
94
+
95
+
.. code-block:: javascript
96
+
97
+
$.ajaxSetup({
98
+
beforeSend: function(xhr, settings) {
99
+
function getCookie(name) {
100
+
var cookieValue = null;
101
+
if (document.cookie && document.cookie != '') {
102
+
var cookies = document.cookie.split(';');
103
+
for (var i = 0; i < cookies.length; i++) {
104
+
var cookie = jQuery.trim(cookies[i]);
105
+
// Does this cookie string begin with the name we want?
106
+
if (cookie.substring(0, name.length + 1) == (name + '=')) {
107
+
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
108
+
break;
109
+
}
110
+
}
111
+
}
112
+
return cookieValue;
113
+
}
114
+
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
115
+
// Only send the token to relative URLs i.e. locally.
116
+
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
117
+
}
118
+
}
119
+
});
120
+
121
+
Adding this to a javascript file that is included on your site will ensure that
122
+
AJAX POST requests that are made via jQuery will not be caught by the CSRF
123
+
protection.
124
+
84
125
The decorator method
85
126
--------------------
86
127
@@ -262,10 +303,6 @@ in the same module. These disable the view protection mechanism
262
303
(``CsrfResponseMiddleware``) respectively. They can be used individually if
263
304
required.
264
305
265
-
You don't have to worry about doing this for most AJAX views. Any request sent
266
-
with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the `How
267
-
it works`_ section.)
268
-
269
306
Subdomains
270
307
----------
271
308
@@ -343,24 +380,6 @@ request ought to be harmless.
343
380
response, and only pages that are served as 'text/html' or
344
381
'application/xml+xhtml' are modified.
345
382
346
-
AJAX
347
-
----
348
-
349
-
The middleware tries to be smart about requests that come in via AJAX. Most
350
-
modern JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP
351
-
header; these requests are detected and automatically *not* handled by this
352
-
middleware. We can do this safely because, in the context of a browser, the
353
-
header can only be added by using ``XMLHttpRequest``, and browsers already
354
-
implement a same-domain policy for ``XMLHttpRequest``.
355
-
356
-
For the more recent browsers that relax this same-domain policy, custom headers
357
-
like "X-Requested-With" are only allowed after the browser has done a
358
-
'preflight' check to the server to see if the cross-domain request is allowed,
359
-
using a strictly 'opt in' mechanism, so the exception for AJAX is still safe—if
360
-
the developer has specifically opted in to allowing cross-site AJAX POST
361
-
requests on a specific URL, they obviously don't want the middleware to disallow
362
-
exactly that.
363
-
364
383
.. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
365
384
366
385
Caching
Original file line number Diff line number Diff line change
@@ -275,12 +275,12 @@ def test_process_request_csrf_cookie_no_token_exempt_view(self):
275
275
req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {})
276
276
self.assertEquals(None, req2)
277
277
278
-
def test_ajax_exemption(self):
278
+
def test_csrf_token_in_header(self):
279
279
"""
280
-
Check that AJAX requests are automatically exempted.
280
+
Check that we can pass in the token in a header instead of in the form
281
281
"""
282
282
req = self._get_POST_csrf_cookie_request()
283
-
req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
283
+
req.META['HTTP_X_CSRFTOKEN'] = self._csrf_id
284
284
req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
285
285
self.assertEquals(None, req2)
286
286
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4