Django, Django REST Framework, Internet Explorer and CSRF token missing or incorrect

三世轮回 提交于 2021-02-08 11:24:21

问题


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:

  1. extranet (domain/extranet/).
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!