Vercel x-forwarded-for IP 地址在应用程序首次加载时(从客户端调用 API 时起)发生变化?

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

背景

我正在构建一个非常简单的博客应用程序。没有认证。每个用户都通过其 IP 地址(存储在数据库中)进行识别,以提供个性化体验,例如为帖子添加书签、评论、点赞等...

应用程序/布局(服务器)

在我的根布局中,我调用 DB 来获取与用户相关的数据。请注意,当用户登陆页面时,它会立即运行。

export default async function RootLayout(props: React.PropsWithChildren) {
  const user = await getUser()
  const store = { user }
  ...
}

服务器/getUser.ts(服务器)

该函数进行数据库调用。不过,在调用之前,我们需要从

headers.get('x-forwarded-for')
获取用户IP地址。

export default async function getUser() {
  const { id: userId } = getUserId()
  ...
}

服务器/getUserId.ts(服务器)

这只是从标头中提取 IP 地址。

export function getUserId() {
  const headers = NextHeaders()

  const fallback = '171.23.136.120' // my Ip address

  // vercel exposes the ip
  let ip = headers.get('x-forwarded-for')

  return {
    id: ip ?? fallback,
  }
}

问题

当用户登陆网站时。应用程序尝试获取 SSR 中有关用户的所有信息(如果数据库中存在),例如书签、点赞、评论等列表...并将其呈现在 UI 中。

但是,从标头返回的 IP 地址与用户进行 API 调用时不同。例如单击按钮即可为帖子添加书签。

我很困惑为什么会出现这种情况,以及如何解决这个问题。

谢谢

vercel next.js13 request-headers
1个回答
0
投票

首先,必须问一个问题:您是否排除了记录来自两个完全不同的用户的交互的可能性?


X-Forwarded-For
标头比您想象的要复杂得多。

  1. 此标头仅在反向代理/负载均衡器实现时才存在。它已被新的
    Forwarded
    标头取代。就您而言,这可能不是问题,因为您知道您已部署在 Vercel 上并且您确实在此标头中获得了值。
  2. 请求中可以存在同一标头的多个副本。你的
    NextHeaders
    对象如何处理这个问题?它是否将它们全部组合成一个字符串数组?它会默默地用后面的条目覆盖前面的条目吗?
  3. 此标头的每个实例中可以有多个逗号分隔的值。这代表
    client, proxy1, proxy2...
    你在处理这个吗?

还有更多的考虑因素,特别是如果您将其用于任何类型的安全性。 MDN 上的整个页面都值得一读:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For

处理多个标头条目:

制作这个单一列表有两种方法:

  • 用逗号连接 X-Forwarded-For 完整标头值,然后用逗号将其拆分为列表,或者
  • 用逗号将每个 X-Forwarded-For 标头拆分为列表,然后加入列表

选择IP

如果您真的关心正确执行此操作,MDN 页面提供了两个选项:

选择第一个可信的X-Forwarded-For客户端IP地址时,需要进行额外的配置。常用的方法有两种:

  • 可信代理数量:互联网之间的反向代理数量 并且服务器已配置。搜索 X-Forwarded-For IP 列表 从最右边算起减一。 (例如,如果有 只有一个反向代理,该代理将添加客户端的 IP 地址, 所以应该使用最右边的地址。如果有三个反向 代理,最后两个 IP 地址将是内部 IP 地址。)

  • 可信代理 list:受信任反向代理的 IP 或 IP 范围是 配置。 X-Forwarded-For IP 列表是从 最右边,跳过受信任代理列表上的所有地址。 第一个不匹配的地址是目标地址。

但大多数人只是选择最左边(第一个)值,在大多数情况下应该是客户端IP。


您可能想要使用第 3 方库(例如,https://www.npmjs.com/package/request-ip),它应该为您处理所有这些情况(除非它无法选择一个适当的值得信赖的 IP,并且只会使用第一个值)。

但是,我不得不说,使用客户端IP来识别用户并不是一个好主意。一所大学可能在同一公共 IP 上拥有数千名用户。


tl;dr 不确定为什么您会遇到这种情况,但可能是测量错误(即,这是两个不同的用户)或 X-Forwarded-For 标头处理不当。

附注也许应该阻止这些 IP 地址。它可能是你的,你不会想对自己进行人肉搜索。

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