Почему не удается получить CSRF-токен Django из файла cookie в мобильном браузере Chrome?

#javascript #reactjs #django #cookies

#javascript #reactjs #django #файлы cookie

Вопрос:

Веб-приложение на Django с компонентами React в настоящее время протестировано и работает в настольных браузерах Google Chrome, Microsoft Edge, mobile Firefox и mobile Brave. К сожалению, это приводит к ошибкам в Google Chrome на мобильных устройствах. Компоненты React, похоже, не распознают, что пользователь вошел в систему.

Токен CSRF передается из Django в компоненты React с использованием файла cookie (аналогично процессу, предложенному в: https://django.readthedocs.io/en/stable/ref/csrf.html ).

 // Set what happens when the database is called by React

// Define how to get a cookie (such as a CSRF token)
export function getCookie(name) {
  var cookieValue = null;
  if (document.cookie amp;amp; document.cookie !== '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i  ) {
          var cookie = cookies[i].trim();
          // 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;
}

// Define generically what happens when the database is called by React
export function backendLookup(method, endpoint, callback, data) {

  // Convert the data being sent to the database to JSON form
  let jsonData;
  if (data){
    jsonData = JSON.stringify(data)
  }

  // Prepare a new request to a database
  const xhr = new XMLHttpRequest()
  
  // Prepare the URL where the database is accessible (the API endpoint)
  const url = `https://artformist.com/api${endpoint}`

  // Identify that the data that will be receievd is in JSON format
  xhr.responseType = "json"

  // Prepare the CSRF security token
  const csrftoken = getCookie('csrftoken');

  // Access the database, using the endpoint and method (such as "POST" or "GET") in use
  xhr.open(method, url)

  // Set the request header, for security purposes
  xhr.setRequestHeader("Content-Type", "application/json")

  // If there is a CSRF token...
  if (csrftoken){

    // Set the request headers
    // xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest")
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
    xhr.setRequestHeader("X-CSRFToken", csrftoken)
  }
  
  // Set what happens immediately when a request is made
  xhr.onload = function() {

    // If the status returned is a 403 error...
    if (xhr.status === 403) {

      // Get the details of the response...
      const detail = xhr.response.detail

      // If the response is that the user wasn't logged in...
      if (detail === "Authentication credentials were not provided."){

        if (window.location.href.indexOf("login") === -1) {

          // Redirect the user to the login screen TURNED OFF FOR TESTING
          // window.location.href = "/login?showLoginRequired=trueamp;status=403"
        }

        alert(xhr.status)
      }
    }

    // // If the response is that something has gone wrong with the server 
    if (xhr.status === 500) {
      
      // If the user isn't at a login screen already...
      if (window.location.href.indexOf("login") === -1) {

          // Redirect the user to the login screen. TURNED OFF FOR TESTING
          // window.location.href = "/login?showLoginRequired=trueamp;status=500"

          alert(xhr.status)
        }
    }

    // Manage the request response and status
    callback(xhr.response, xhr.status)
  }

  // If there is an error when the call to the database is made
  xhr.onerror = function (e) {
    
    // Manage that there was a 400 error
    callback({"message": "The request was an error"}, 400)
  }

  // Send the JSON data
  xhr.send(jsonData)

}
  

В Chrome mobile сайт выдает ошибку 403 или 500 в зависимости от того, что пытается выполнить компонент.

Вот некоторые производственные настройки. Настройки того же сайта были изменены, и версия Django была обновлена.

 CORS_REPLACE_HTTPS_REFERER      = True
HOST_SCHEME                     = "https://"
SECURE_PROXY_SSL_HEADER         = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT             = True
SESSION_COOKIE_SECURE           = True
CSRF_COOKIE_SECURE              = True

# Set whether requests can be made from different sites
CSRF_COOKIE_SAMESITE = None
SESSION_COOKIE_SAMESITE = None

SECURE_HSTS_INCLUDE_SUBDOMAINS  = True
SECURE_HSTS_SECONDS             = 1000000
SECURE_FRAME_DENY               = True
  

Комментарии:

1. Похоже, что он работает в мобильном браузере Chrome на iPhone, но имеет проблемы с Pixel 3, на котором я его тестировал. Странно.