| 89 | | that allow headers to be set on every request. In jQuery, you can use the |
| 90 | | ``ajaxSend`` event as follows: |
| | 89 | that allow headers to be set on every request. |
| | 90 | |
| | 91 | As a first step, you must get the CSRF token itself. The recommended source for |
| | 92 | the token is the ``csrftoken`` cookie, which will be set if you've enabled CSRF |
| | 93 | protection for your views as outlined above. |
| | 94 | |
| | 95 | .. note:: |
| | 96 | |
| | 97 | The CSRF token cookie is named ``csrftoken`` by default, but you can control |
| | 98 | the cookie name via the :setting:`CSRF_COOKIE_NAME` setting. |
| | 99 | |
| | 100 | Acquiring the token is straightforward: |
| 94 | | jQuery(document).ajaxSend(function(event, xhr, settings) { |
| 95 | | function getCookie(name) { |
| 96 | | var cookieValue = null; |
| 97 | | if (document.cookie && document.cookie != '') { |
| 98 | | var cookies = document.cookie.split(';'); |
| 99 | | for (var i = 0; i < cookies.length; i++) { |
| 100 | | var cookie = jQuery.trim(cookies[i]); |
| 101 | | // Does this cookie string begin with the name we want? |
| 102 | | if (cookie.substring(0, name.length + 1) == (name + '=')) { |
| 103 | | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
| 104 | | break; |
| 105 | | } |
| 106 | | } |
| 107 | | } |
| | 104 | |
| | 105 | // using jQuery |
| | 106 | function getCookie(name) { |
| | 107 | var cookieValue = null; |
| | 108 | if (document.cookie && document.cookie != '') { |
| | 109 | var cookies = document.cookie.split(';'); |
| | 110 | for (var i = 0; i < cookies.length; i++) { |
| | 111 | var cookie = jQuery.trim(cookies[i]); |
| | 112 | // Does this cookie string begin with the name we want? |
| | 113 | if (cookie.substring(0, name.length + 1) == (name + '=')) { |
| | 114 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
| | 115 | break; |
| 109 | | } |
| 110 | | function sameOrigin(url) { |
| 111 | | // url could be relative or scheme relative or absolute |
| 112 | | var host = document.location.host; // host + port |
| 113 | | var protocol = document.location.protocol; |
| 114 | | var sr_origin = '//' + host; |
| 115 | | var origin = protocol + sr_origin; |
| 116 | | // Allow absolute or scheme relative URLs to same origin |
| 117 | | return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || |
| 118 | | (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || |
| 119 | | // or any other URL that isn't scheme relative or absolute i.e relative. |
| 120 | | !(/^(\/\/|http:|https:).*/.test(url)); |
| 121 | | } |
| 122 | | function safeMethod(method) { |
| 123 | | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); |
| 124 | | } |
| | 117 | } |
| | 118 | var csrftoken = getCookie('csrftoken'); |
| | 119 | |
| | 120 | The above code could be simplified by using the `jQuery cookie plugin |
| | 121 | <http://plugins.jquery.com/project/Cookie>`_ to replace ``getCookie``: |
| | 122 | |
| | 123 | .. code-block:: javascript |
| | 124 | |
| | 125 | var csrftoken = $.cookie('csrftoken'); |
| 140 | | The above code could be simplified by using the `jQuery cookie plugin |
| 141 | | <http://plugins.jquery.com/project/Cookie>`_ to replace ``getCookie``, and |
| 142 | | `settings.crossDomain <http://api.jquery.com/jQuery.ajax>`_ in jQuery 1.5 and |
| 143 | | later to replace ``sameOrigin``. |
| | 138 | If your view is not rendering a template containing the :ttag:`csrf_token` |
| | 139 | template tag, Django might not set the CSRF token cookie. This is common in |
| | 140 | cases where forms are dynamically added to the page. To address this case, |
| | 141 | Django provides a view decorator which forces setting of the cookie: |
| | 142 | :func:`~django.views.decorators.csrf.ensure_csrf_cookie`. |
| | 143 | |
| | 144 | Finally, you'll have to actually set the header on your AJAX request, while |
| | 145 | protecting the CSRF token. |
| | 146 | |
| | 147 | .. code-block:: javascript |
| | 148 | |
| | 149 | function csrfSafeMethod(method) { |
| | 150 | // these HTTP methods do not require CSRF protection |
| | 151 | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); |
| | 152 | } |
| | 153 | function sameOrigin(url) { |
| | 154 | // test that a given url is a same-origin URL |
| | 155 | // url could be relative or scheme relative or absolute |
| | 156 | var host = document.location.host; // host + port |
| | 157 | var protocol = document.location.protocol; |
| | 158 | var sr_origin = '//' + host; |
| | 159 | var origin = protocol + sr_origin; |
| | 160 | // Allow absolute or scheme relative URLs to same origin |
| | 161 | return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || |
| | 162 | (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || |
| | 163 | // or any other URL that isn't scheme relative or absolute i.e relative. |
| | 164 | !(/^(\/\/|http:|https:).*/.test(url)); |
| | 165 | } |
| | 166 | $.ajaxSetup({ |
| | 167 | beforeSend: function(xhr, settings) { |
| | 168 | if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) { |
| | 169 | // Send the token to same-origin, relative URLs only. |
| | 170 | // Send the token only if the method warrants CSRF protection |
| | 171 | // Using the CSRFToken value acquired earlier |
| | 172 | xhr.setRequestHeader("X-CSRFToken", csrftoken); |
| | 173 | } |
| | 174 | } |
| | 175 | }); |
| | 176 | |
| | 177 | You can use `settings.crossDomain <http://api.jquery.com/jQuery.ajax>`_ in |
| | 178 | jQuery 1.5 and newer in order to replace the `sameOrigin` logic above: |
| | 179 | |
| | 180 | .. code-block:: javascript |
| | 181 | |
| | 182 | function csrfSafeMethod(method) { |
| | 183 | // these HTTP methods do not require CSRF protection |
| | 184 | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); |
| | 185 | } |
| | 186 | $.ajaxSetup({ |
| | 187 | crossDomain: false, // obviates need for sameOrigin test |
| | 188 | beforeSend: function(xhr, settings) { |
| | 189 | if (!csrfSafeMethod(settings.type)) { |
| | 190 | xhr.setRequestHeader("X-CSRFToken", csrftoken); |
| | 191 | } |
| | 192 | } |
| | 193 | }); |
| | 194 | |
| | 195 | .. note:: |
| | 196 | |
| | 197 | In a `security release blogpost`_, a simpler "same origin test" example |
| | 198 | was provided which only checked for a relative URL. The ``sameOrigin`` |
| | 199 | test above supersedes that example—it works for edge cases like |
| | 200 | scheme-relative or absolute URLs for the same domain. |