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

问题描述 投票:0回答:1

我有一个运行在

http://localhost:5173
的 SvelteKit 应用程序(在进行本地开发时),它前面有一个运行在
http://localhost:8057
的 Nginx,提供一些必须由 SvelteKit 处理的静态文件和代理请求。

我在

http://localhost:8057/login
有一个登录表单,当我提交它时,我得到的网页只有 “禁止跨站点 POST 表单提交”.

我尝试根据

跨站点 POST 表单提交被禁止
https://kit.svelte.dev/docs/adapter-node#environment-variables使用ORIGIN环境变量。这是我的
.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 表单”。知道我还能尝试什么吗?

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

cross-domain csrf sveltekit
1个回答
0
投票

问题来自于我处于开发模式 (

npm run dev
) 并且
PROTOCOL_HEADER
HOST_HEADER
ORIGIN
环境变量记录在https://kit.svelte.dev/docs/adapter- node#environment-variables 适用于节点适配器(当您以 NodeJS 为目标执行
npm run build
时使用)但不适用于 Vite 开发服务器。

消息“禁止跨站点POST表单提交”来自

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

您在本文中读到的“解决方案”是使用

PROTOCOL_HEADER
HOST_HEADER
ORIGIN
环境变量,但这些只有节点适配器才能理解。你可以看到它们被用于
packages/adapter-node/src/handler.js
.

当您使用

npm run dev
运行 SvelteKit 应用程序时,您没有使用 NodeJS 适配器。您使用的是 Vite 开发服务器,它不会读取这些环境变量。您可以在
packages/kit/src/exports/vite/dev/index.js
中看到这个开发服务器如何设置请求的“来源”。它仅使用请求的“主机”标头,但忽略任何“x-forwarded-host”或其他类似标头。

一个解决方案是让您的代理设置“主机”HTTP 标头。不要在生产中这样做,但在开发模式下应该没问题。另一个是在开发模式下禁用 CSRF 保护。

SvelteKit 的 GitHub 存储库中已经有关于此的问题:https://github.com/sveltejs/kit/issues/8026

© www.soinside.com 2019 - 2024. All rights reserved.