#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, на котором я его тестировал. Странно.