У меня есть приложение SvelteKit, работающее на http://localhost:5173
(при локальной разработке) с Nginx перед ним, работающим на http://localhost:8057
, обслуживающим некоторые статические файлы и проксирующие запросы, которые должны обрабатываться SvelteKit.
У меня есть форма входа в http://localhost:8057/login
, и когда я отправляю ее, я получаю веб-страницу с надписью «Отправка кросс-сайтовых форм POST запрещена».
Я попытался использовать переменную среды ORIGIN
в соответствии с Отправка форм POST между сайтами запрещена и https://kit.svelte.dev/docs/adapter-node#environment-variables. Вот мой .env
файл:
ORIGIN=http://localhost:8057
Я вижу эту переменную среды в своей среде, если я регистрирую env
из import { env } from '$env/dynamic/private';
на стороне сервера. Но я все еще получаю сообщение «Отправка межсайтовых форм POST запрещена».
Я также пытался передать переменную окружения при запуске SvelteKit (с помощью ORIGIN=http://localhost:8057 npm run dev
), но результат тот же.
Поскольку SvelteKit не очень много записывает в журнал, когда отправляет эту ошибку, я могу просто попытаться угадать, что происходит внутри SvelteKit, но если в Nginx я добавлю proxy_set_header Origin http://localhost:5173;
, тогда это сработает, поэтому довольно ясно, какое происхождение SvelteKit ожидает здесь. Однако я бы предпочел не делать этого, потому что это в значительной степени эквивалентно отключению защиты CSRF.
Затем я попытался использовать другой метод, предложенный в https://kit.svelte.dev/docs/adapter-node#environment-variables, то есть использовать x-forwarded-proto
и x-forwarded-host
, так что теперь вот мой .env
файл ( и снова я могу определенно увидеть эти значения, если я зарегистрирую их в своем приложении):
PROTOCOL_HEADER=x-forwarded-proto
HOST_HEADER=x-forwarded-host
ORIGIN=http://localhost:8057
и в моей конфигурации Nginx (то самое место, где замена заголовка Origin все исправит):
location @sveltekit {
proxy_pass http://localhost:5173;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
}
И я все еще получаю сообщение «Отправка кросс-сайтовых форм POST запрещена». Любая идея, что еще я мог бы попробовать?
На случай, если люди захотят увидеть или запустить код:
docker-compose up --build
для запуска Nginxcd web-app; npm run dev
для запуска приложения SvelteKit (сначала может потребоваться npm install
)Проблема заключалась в том, что я был в режиме разработки (npm run dev
) и что переменные среды PROTOCOL_HEADER
, HOST_HEADER
и ORIGIN
, задокументированные в https://kit.svelte.dev/docs/adapter-node#environment-variables, работают для адаптер узла (который используется, когда вы делаете npm run build
при нацеливании на NodeJS), но не для сервера разработки Vite.
Сообщение «Отправка межсайтовых POST-форм запрещена» исходит от packages/kit/src/runtime/server/respond.js , который не привязан к адаптеру узла, он запускает любой адаптер, который вы используете. Что вводит в заблуждение, так это то, что если вы будете искать это сообщение об ошибке, вы прочитаете о нем только в контексте, связанном с адаптером NodeJS, например https://kit.svelte.dev/docs/adapter-node#environment- переменные.
«Решение», о котором вы читали в этом контексте, заключается в использовании переменных среды PROTOCOL_HEADER
, HOST_HEADER
и ORIGIN
, но они понятны только адаптеру узла. Вы можете увидеть их использование в packages/adapter-node/src/handler.js.
Когда вы запускаете приложение SvelteKit с помощью npm run dev
, вы не используете адаптер NodeJS. Вы используете сервер разработки Vite, который не читает эти переменные среды. Вы можете увидеть, как этот сервер разработки устанавливает «происхождение» запроса в packages/kit/src/exports/vite/dev/index.js. Он использует только заголовок «host» запроса, но игнорирует любой «x-forwarded-host» или другие подобные заголовки.
Одним из решений является установка прокси-сервером HTTP-заголовка host. Не делайте этого в продакшене, но в режиме разработки все должно быть в порядке. Другой способ — отключить защиту CSRF в режиме разработки.
В репозитории SvelteKit на GitHub уже есть проблема по этому поводу: https://github.com/sveltejs/kit/issues/8026