问题
We have a Django App using REST Framework. It is a nginx, redis, celery, gunicorn and PostgreSQL setup. There is only one App server.
Our ajax calls use this function :
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
...
jqXHR.setRequestHeader("X-CSRFToken", secureCheck.reqCSRFToken());
})
if ($currentForm.attr('method') != 'POST') {
if ($currentForm.attr('method') != '') {
var typeRequest = $currentForm.attr('method');
headersRequest= {'X-HTTP-Method-Override': typeRequest};
}
}
var jqxhr = $.ajax({
headers: headersRequest,
url: url,
type: 'POST',
dataType: dataType,
data: params,
async: async
});
jqxhr
.done(function (data, textStatus, jqxhr) {
Calls are sent to this :
@api_view(['POST'])
def save(request):
.....
return HttpResponse(json.dumps(save_results_and_errors, cls=DjangoJSONEncoder), 'application/json')
settings.py :
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
also :
'django.middleware.csrf.CsrfViewMiddleware'
We never got any kind of error related to CSRF except for some people, one out of six, using Internet Explorer (version 9 or 11). The "save" function keeps returning an error {"detail":"CSRF Failed: CSRF token missing or incorrect."}.
Clearing IE history, cache and cookies did not worked. The only way to solve this was to restart the computer (???!!).
How can i track down this behavior ? We do not have any iframe in any web page. Nothing in our log files is related to this issue.
Does anybody have a clue on this ?
回答1:
Found it ! Well, it is documented by Microsoft...
Our production app has two login schemes:
- extranet (domain/extranet/).
- intranet (subdomain.domain/intranet/) : will be replaced with subdomainname/intranet within a few months.
If we login into extranet and thereafter into the intranet, we have two csrf tokens related to the domain. So reqCSRFToken() was getting two CSRF tokens and was using the wrong one (the first that matched "csrftoken") because Internet Explorer sends the domain cookie to the subdomain.
reqCSRFToken: function () {
var csrfTokenValeur = secureCheck.reqCookie('csrftoken');
return csrfTokenValeur;
},
reqCookie: function (name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
},
https://stackoverflow.com/a/17371607/2257881 https://blogs.msdn.microsoft.com/ieinternals/2009/08/20/internet-explorer-cookie-internals-faq/
来源:https://stackoverflow.com/questions/43400660/django-django-rest-framework-internet-explorer-and-csrf-token-missing-or-incor