使用 origin 和 x-forwarded 时,开发模式下 SvelteKit 出现“禁止跨站点 POST 表单提交”错误

Céd*_*pay 2 csrf cross-domain sveltekit

我有一个 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
Run Code Online (Sandbox Code Playgroud)

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-protox-forwarded-host,所以现在这是我的.env文件(我再次可以肯定地看到如果我将这些值记录在我的应用程序中):

PROTOCOL_HEADER=x-forwarded-proto
HOST_HEADER=x-forwarded-host
ORIGIN=http://localhost:8057
Run Code Online (Sandbox Code Playgroud)

在我的 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;
}
Run Code Online (Sandbox Code Playgroud)

我仍然收到“禁止跨站点 POST 表单提交”的信息。知道我还能尝试什么吗?

如果人们想查看或运行代码:

Céd*_*pay 9

问题来自于我处于开发模式 ( npm run dev) 并且https://kit.svelte.dev/docs/adapter-node#environment-variablesPROTOCOL_HEADER中记录的HOST_HEADERORIGIN环境变量适用于节点适配器(用于当你针对 NodeJS 时这样做),但不适用于 Vite 开发服务器。npm run build

消息“禁止跨站点 POST 表单提交”来自packages/kit/src/runtime/server/respond.js该消息,该消息与节点适配器无关,它运行您正在使用的任何适配器。具有误导性的是,如果您搜索此错误消息,您只会在与 NodeJS 适配器相关的上下文中阅读它,例如https://kit.svelte.dev/docs/adapter-node#environment-variables

您在本文中读到的“解决方案”是使用PROTOCOL_HEADER,HOST_HEADERORIGIN环境变量,但这些变量只能被节点适配器理解。您可以看到它们被用于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 标头。不要在生产中这样做,但在开发模式下这应该没问题。另一种是在开发模式下禁用 CSRF 保护。

SvelteKit 的 GitHub 存储库中已经存在一个与此相关的问题: https: //github.com/sveltejs/kit/issues/8026