You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js(Express)获取移动端真实IP及设备IP限流实现问题

问题解答

一、为什么获取的IP是本地回环地址或IPv6地址?

1. 本地回环地址:1(即::1)的原因

这种情况多发生在本地开发场景:你的React Native真机通过Expo Go访问本地后端时,请求大概率经过了Expo的本地代理转发,后端实际收到的请求来自代理服务器的本地回环地址,而非手机的真实IP。另外,如果你的Express服务器仅监听localhost/127.0.0.1(未监听0.0.0.0),也会导致请求被代理转发后显示回环地址。

2. 拿到IPv6地址的原因

现在多数设备和网络默认优先支持IPv6协议,当你的手机和后端处于IPv6网络环境(比如局域网开启了IPv6),请求会通过IPv6链路传输,此时获取到的IPv6地址就是设备的真实IP,并非无效地址。

二、如何实现基于设备IP的用户限流?

第一步:确保正确获取设备真实IP

  • 本地开发场景:先配置Express信任代理,在代码开头添加app.set('trust proxy', 'loopback'),让req.ip能正确解析经过Expo代理后的客户端IP;同时确保Express服务器监听0.0.0.0(而非localhost),比如启动命令用app.listen(3000, '0.0.0.0')。
  • 生产环境(有Nginx/Cloudflare等反向代理):同样需要设置app.set('trust proxy', true)(或指定代理IP范围),这样req.ip和req.headers['x-forwarded-for']才能拿到真实的客户端IP。

第二步:使用限流中间件实现IP限流

推荐用express-rate-limit这个轻量的Express限流库,步骤如下:

  1. 安装依赖:
npm install express-rate-limit
  1. 在Express中配置限流规则:
const rateLimit = require('express-rate-limit');

// 配置限流规则
const ipLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 时间窗口:15分钟
  max: 100, // 每个IP在窗口内最多允许100次请求
  // 自定义IP获取逻辑,优先取代理传递的真实IP
  keyGenerator: (req) => {
    // 从x-forwarded-for中取第一个IP(避免多级代理的情况),没有则用req.ip或连接地址
    const clientIp = req.headers['x-forwarded-for']?.split(',')[0].trim() 
                     || req.ip 
                     || req.connection.remoteAddress;
    return clientIp;
  },
  handler: (req, res) => {
    res.status(429).json({ message: '请求过于频繁,请15分钟后再试' });
  }
});

// 应用到所有API路由
app.use('/api', ipLimiter);

注意事项

  • IPv6地址可以直接作为限流的标识,express-rate-limit完全支持IPv6格式的IP作为key。
  • 移动网络下,设备的公网IP其实是基站(路由器)的IP,同基站下的设备会共享这个IP,这种场景下无法通过IP区分单个设备,若需要更精准的限流,可结合客户端生成的唯一设备UUID(存在本地存储,每次请求携带),但这已经超出纯IP限流的范畴。

内容的提问来源于stack exchange,提问作者learncode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:15:31