diff --git a/docs/ref/contrib/csrf.txt b/docs/ref/contrib/csrf.txt
index a683947..0e1935d 100644
a
|
b
|
inconveniences: you have to remember to pass the CSRF token in as POST data with
|
86 | 86 | every POST request. For this reason, there is an alternative method: on each |
87 | 87 | XMLHttpRequest, set a custom `X-CSRFToken` header to the value of the CSRF |
88 | 88 | token. This is often easier, because many javascript frameworks provide hooks |
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 a hold of the CSRF token itself. If you've got |
| 92 | a form which was rendered with the :ttag:`csrf_token`, then you can extract the |
| 93 | token from there: |
| 94 | |
| 95 | .. code-block:: javascript |
| 96 | |
| 97 | // jQuery |
| 98 | var csrftoken = $("input[name=csrfmiddlewaretoken]").val(); |
| 99 | |
| 100 | If the CSRF token is not present in markup by use of the :ttag:`csrf_token` |
| 101 | template tag, it must be supplied to the client by other means. This is common |
| 102 | in cases where the form is dynamically added to the page, and Django supplies |
| 103 | a decorator which will set a cookie containing the CSRF token: |
| 104 | :func:`~django.views.decorators.csrf.ensure_csrf_cookie`. Use the decorator |
| 105 | on any view which will need access to the CSRF token, but doesn't include the |
| 106 | token in the actual markup sent to the client. |
91 | 107 | |
92 | 108 | .. code-block:: javascript |
93 | 109 | |
94 | | $(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 | | } |
| 110 | // once again, using jQuery |
| 111 | function getCookie(name) { |
| 112 | var cookieValue = null; |
| 113 | if (document.cookie && document.cookie != '') { |
| 114 | var cookies = document.cookie.split(';'); |
| 115 | for (var i = 0; i < cookies.length; i++) { |
| 116 | var cookie = jQuery.trim(cookies[i]); |
| 117 | // Does this cookie string begin with the name we want? |
| 118 | if (cookie.substring(0, name.length + 1) == (name + '=')) { |
| 119 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
| 120 | break; |
106 | 121 | } |
107 | 122 | } |
108 | | return cookieValue; |
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 | 123 | } |
| 124 | return cookieValue; |
| 125 | } |
| 126 | var csrftoken = getCookie('csrftoken'); |
125 | 127 | |
126 | | if (!safeMethod(settings.type) && sameOrigin(settings.url)) { |
127 | | xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); |
128 | | } |
129 | | }); |
| 128 | The above code could be simplified by using the `jQuery cookie plugin |
| 129 | <http://plugins.jquery.com/project/Cookie>`_ to replace ``getCookie``: |
130 | 130 | |
131 | | .. note:: |
| 131 | .. code-block:: javascript |
132 | 132 | |
133 | | Due to a bug introduced in jQuery 1.5, the example above will not work |
134 | | correctly on that version. Make sure you are running at least jQuery 1.5.1. |
| 133 | var csrftoken = $.cookie('csrftoken'); |
135 | 134 | |
136 | | Adding this to a javascript file that is included on your site will ensure that |
137 | | AJAX POST requests that are made via jQuery will not be caught by the CSRF |
138 | | protection. |
| 135 | Finally, you'll have to actually set the header on your AJAX request, while |
| 136 | protecting the CSRF token from being sent to other domains: |
139 | 137 | |
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 | .. code-block:: javascript |
| 139 | |
| 140 | function safeMethod(method) { |
| 141 | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); |
| 142 | } |
| 143 | $.ajaxSetup({ |
| 144 | beforeSend: function(xhr, settings) { |
| 145 | if (!(/^https?:.*/.test(settings.url)) && safeMethod(settings.type) ) { |
| 146 | // Only send the token to relative URLs i.e. locally. |
| 147 | // Only send the token when using a safe HTTP method. |
| 148 | // Using the csrftoken value acquired earlier. |
| 149 | xhr.setRequestHeader("X-CSRFToken", csrftoken); |
| 150 | } |
| 151 | } |
| 152 | }); |
| 153 | |
| 154 | You can use `settings.crossDomain <http://api.jquery.com/jQuery.ajax>`_ in |
| 155 | jQuery 1.5 and newer in order to simplify the above code: |
144 | 156 | |
145 | | In addition, if the CSRF cookie has not been sent to the client by use of |
146 | | :ttag:`csrf_token`, you may need to ensure the client receives the cookie by |
147 | | using :func:`~django.views.decorators.csrf.ensure_csrf_cookie`. |
| 157 | .. code-block:: javascript |
| 158 | |
| 159 | $.ajaxSetup({ |
| 160 | crossDomain: false, |
| 161 | beforeSend: function(xhr, settings) { |
| 162 | if (safeMethod(settings.type) { |
| 163 | xhr.setRequestHeader("X-CSRFToken", csrftoken); |
| 164 | } |
| 165 | } |
| 166 | }); |
148 | 167 | |
149 | 168 | The decorator method |
150 | 169 | -------------------- |