Django не создает куки сессии в межсайтовом json-запросе
Я хочу сделать межсайтовый JavaScript вызов из стороннего домена (в данном случае с моего рабочего стола/сервера localhost) на мой удаленный сервер Django, расположенный на my_domain.com/, и вызвать REST WS, открытый на my_domain.com/msg/my_service с использованием session/cookies для хранения состояния сессии.
Но когда я вызываю этот сервис (размещенный на удаленном Django сервере) из браузера моего рабочего стола или с локалхостового Django сервера (JS находится в index.html), Django не создает куки сессии и на удаленном сервере не хранится состояние сессии. Но когда я вызываю этот сервис из Postman или из того же localhost JS на localhost экземпляр того же сервиса Django, он работает и сессия создается.
Мой JS скрипт в index.html, который делает вызов WS send_message:
fetch('http://my_domain.com/ws/my_service', {
method:"POST",
credentials: 'include',
body:JSON.stringify(data)
})
.then(res => res.json())
.then(json => {
showResponse(json.message);
})
Когда я запускаю этот скрипт из браузера на рабочем столе или с сервера localhost, он работает правильно с параметрами cookies и сессий.
Django представление реализации my_service
@csrf_exempt
def my_service(request):
if request.method == "POST":
message_bstream= request.body
request.session.set_expiry(0)
message= json.loads(message_bstream)
out,sta=state_machine_response(message["message"],int(request.session["state"]))
request.session["state"] =sta
respo={"message":out}
response = HttpResponse(json.dumps(respo), content_type="application/json")
response.set_cookie(key='name', value='my_value', samesite='None', secure=True)
#return JsonResponse(respo, safe=False, status=200)
return response
else:
return HttpResponseNotFound ("Sorry this methode is not allowed")
Или я пытаюсь сгенерировать ответ типа
return JsonResponse(respo, safe=False, status=200)
Мой settings.py
INSTALLED_APPS = [
...
'corsheaders',
]
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:8000',
)
CORS_ALLOWED_ORIGINS = [
'http://localhost:8000',
]
CSRF_TRUSTED_ORIGINS = [
'http://localhost:8000',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
Пожалуйста, у вас есть какие-нибудь идеи?
Вы не сможете сохранить куки от стороннего вызова API, если не используете SameSite=None с опцией Secure в заголовке Set-Cookie. Вы можете добиться этого для sessionid и CSRF cookie с помощью следующих настроек:
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
В этом случае вы должны использовать схему протокола HTTPS.
Другим решением может быть использование прокси, что полезно в среде разработки на локальном хосте. Вот пример использования vue.js на файле vue.config.js:
const { defineConfig } = require('@vue/cli-service')
if (process.env.NODE_ENV == "development"){
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
"^/api/": {
target: process.env.VUE_APP_BASE_URL,
changeOrigin: true,
logLevel: "debug",
pathRewrite: { "^/api": "/api" }
}
}
},
})
}
Полезный документ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#samesitenone_requires_secure