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

在Heroku上使用Express.js获取客户端真实IP的方法

解决Heroku上Express获取客户端真实IP并适配express-rate-limit的问题

核心问题原因

Heroku的反向代理会屏蔽客户端真实IP,默认情况下Express拿到的是代理服务器的IP。虽然设置了trust proxy,但还需要适配Heroku的请求头规则,同时调整express-rate-limit的IP提取逻辑才能生效。

解决方案步骤

  1. 正确配置trust proxy(必须放在所有中间件之前)
    Heroku的代理IP段会动态变化,直接设置为true来信任所有代理节点:
const app = express();
// 这行必须放在app.use(limiter)、cors等所有中间件之前
app.set('trust proxy', true);

const http = require("http");
const server = http.createServer(app);

// 后续的cors、bodyParser等中间件配置...
  1. 修改express-rate-limit的IP提取逻辑
    Heroku会在请求头X-Forwarded-For中传递客户端真实IP(格式通常为客户端IP, 代理IP1, 代理IP2),需要手动提取第一个IP作为限流依据:
const limiter = rateLimit({
  windowMs: 60 * 1000, // 1分钟
  max: 15, // 每个IP每分钟最多15次请求
  message: "Woah! Slow down there cowboy. You can try again in 2 minutes.",
  // 自定义IP提取逻辑
  keyGenerator: (req) => {
    // 优先从X-Forwarded-For取真实IP, fallback到req.ip
    const clientIp = req.headers['x-forwarded-for']?.split(',')[0]?.trim() || req.ip;
    return clientIp;
  },
  onLimitReached: async function(req, res, options) {
    try{
      // 直接使用限流器生成的key(即真实客户端IP)
      const clientIp = options.key;
      console.log(`Rate limit exceeded for IP: ${clientIp}`);

      if(clientIp){
        const geoInfo = await getGeoInfo(clientIp); 
        // 发送Slack通知逻辑
      }else{
        // 无IP的通知逻辑
      }
    }catch(err){
      console.error('[E353]',err);
    }
  }
});

验证方式

可以新增测试路由确认是否拿到真实IP:

app.get('/test-ip', (req) => {
  console.log('X-Forwarded-For:', req.headers['x-forwarded-for']);
  console.log('真实客户端IP:', req.ip);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:17:20