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

Vercel部署Nuxt 3首次SSR加载时未向Laravel后端传递客户端IP的问题

解决方案:Nuxt 3(Vercel)SSR场景下传递客户端真实IP到Laravel后端

核心思路

Vercel在SSR环境中会将客户端真实IP放在专属的x-vercel-ip请求头中,通过转发这个头部到Laravel,并配置Laravel信任该头部及Vercel代理,即可解决IP传递问题,同时避免触发Cloudflare安全机制。

步骤1:Nuxt端转发Vercel提供的真实IP

修改Nuxt的请求拦截器(或sanctumClient配置),从SSR上下文的请求头中获取x-vercel-ip,并通过自定义头部(如X-Client-IP)传递给Laravel API:

interceptors: {
  onRequest: (_app, ctx, _logger) => {
    // 仅获取Vercel提供的真实IP头部
    const { 'x-vercel-ip': clientIp } = useRequestHeaders(['x-vercel-ip']);
    if (clientIp) {
      // 用自定义头部传递,避免与Cloudflare的X-Forwarded-For冲突
      ctx.options.headers['X-Client-IP'] = clientIp;
    }
  },
},

步骤2:Laravel端配置信任代理与自定义头部

  1. 更新TrustProxies中间件
    编辑app/Http/Middleware/TrustProxies.php,指定信任Vercel的代理IP段(可从Vercel官方文档获取最新IP范围),并添加自定义头部的解析规则:

    use Illuminate\Http\Request;
    
    class TrustProxies extends \Illuminate\Http\Middleware\TrustProxies
    {
        // Vercel官方IP段,示例值请替换为最新范围
        protected $proxies = [
            '10.0.0.0/8',
            '172.16.0.0/12',
            '192.168.0.0/16',
            // 补充Vercel的公网IP段
        ];
    
        protected $headers = Request::HEADER_X_FORWARDED_ALL | Request::HEADER_X_REAL_IP;
    }
    
  2. 优先从自定义头部获取IP
    确保限流、定位功能优先使用真实IP,可在Laravel业务逻辑中直接读取X-Client-IP头部:

    // 获取客户端真实IP
    $clientIp = request()->header('X-Client-IP', request()->ip());
    
    // 用于限流逻辑示例
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(60)->by($request->header('X-Client-IP', $request->ip()));
    });
    

步骤3:验证配置有效性

  • 部署修改后的代码到Vercel和Laravel
  • 首次加载SSR页面,检查Laravel日志中的请求IP是否为客户端真实IP
  • 测试限流、定位功能是否正常工作

为什么之前的方案无效?

  • trustproxies: *:Laravel对泛用的*信任规则有严格限制,且未指定正确的代理IP段,导致无法正确解析客户端IP
  • 转发X-Forwarded-For:Cloudflare会自行维护该头部,手动设置会被判定为伪造请求,触发安全拦截

内容的提问来源于stack exchange,提问作者Carlos Valdes Web

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:51:09