我有一个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
如果我从服务器端的import { env } from '$env/dynamic/private';
记录env
,我可以在我的环境中看到这个环境变量。但是我仍然收到"禁止跨站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表单提交是被禁止的">。你知道我还能尝试什么吗?
如果人们想要查看或运行代码:
- https://gitlab.com/cedricvanrompay/mazette/-/commit/bfa59261b8e5e5c95ac0bec37524a878cd815e91
cd web-app; npm run dev
运行SvelteKit应用程序(可能首先需要npm install
)- 在Mac上,由于docker主机网络模式在Mac上不工作,您将不得不恢复此提交:https://gitlab.com/cedricvanrompay/mazette/-/commit/fee6fcd753b2844de307feb8acefd2898bb6efcd
docker-compose up --build
启动Nginx问题来自于我处于开发模式(npm run dev
),并且在https://kit.svelte.dev/docs/adapter-node#environment-variables中记录的PROTOCOL_HEADER
,HOST_HEADER
和ORIGIN
环境变量适用于节点适配器(当您针对NodeJS执行npm run build
时使用),但不适用于Vite开发服务器。
消息"禁止跨站点POST表单提交">来自packages/kit/src/runtime/server/respond.js
,它与节点适配器无关,它运行您正在使用的任何适配器。误导人的是,如果你搜索这个错误消息,你只会在与NodeJS适配器相关的上下文中看到它,比如https://kit.svelte.dev/docs/adapter-node#environment-variables。
"solution"您在本文中所读到的内容是使用PROTOCOL_HEADER
、HOST_HEADER
和ORIGIN
环境变量,但是只有节点适配器才能理解这些变量。您可以在packages/adapter-node/src/handler.js
中看到它们的使用。
当你使用npm run dev
运行SvelteKit应用程序时,你没有使用NodeJS适配器。您正在使用不读取这些环境变量的Vite开发服务器。您可以看到这个开发服务器是如何设置"origin"的。packages/kit/src/exports/vite/dev/index.js
中的请求。它只使用"主机"。请求的头,但忽略任何"x-forwarded-host"或其他类似的头文件
一个解决方案是让你的代理设置"主机";HTTP报头。不要在生产环境中这样做,但在开发模式下应该没问题。另一种是在dev模式下禁用CSRF保护。
SvelteKit的GitHub仓库中已经有一个问题:https://github.com/sveltejs/kit/issues/8026