Laravel怎么获取用户IP地址_Laravel Request获取真实IP方法【基础】

1次阅读

Request::ip() 默认返回代理IP而非真实IP,需正确配置TrustProxies中间件及$proxies、$headers才能解析X-forwarded-For获取真实IP,手动读取$_SERVER存在安全风险。

Laravel怎么获取用户IP地址_Laravel Request获取真实IP方法【基础】

Request::ip() 返回的是代理IP而不是真实IP

直接调用 Request::ip()$request->ip() 在有 nginx、Cloudflare、cdn负载均衡的环境下,通常拿到的是最后一层代理(比如 Nginx)的 IP,而非用户真实出口 IP。这是因为 http 请求头中的 X-Forwarded-For 才可能携带原始客户端 IP,而 laravel 默认不信任这些头字段。

必须配置 trusted proxies 才能解析真实 IP

Laravel 的 IP 解析逻辑依赖 Trustedproxy 中间件是否启用,以及 appHttpMiddlewareTrustProxies 中的 $proxies$headers 配置。没配对的话,Request::ip() 就不会去读 X-Forwarded-For

  • 如果服务器直连用户(无任何代理),保持 $proxies = NULL 即可,Request::ip() 是准确的
  • 如果有 Nginx 反代,把 Nginx 服务器 IP 加到 $proxies = ['127.0.0.1', '192.168.1.10'];或设为 '*'(仅限内网可信环境)
  • 若使用 Cloudflare,需设置 $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO;,并把 Cloudflare 的 IP 段加入 $proxies(或改用 Cloudflare Trusted Proxy 包)
  • 注意:Laravel 5.5+ 默认启用 TrustProxies 中间件,但 $proxies 默认是 null,等于没生效

获取真实 IP 的安全写法不是靠 $_SERVER

别手动读 $_SERVER['HTTP_X_FORWARDED_FOR'] 或拼接字符串——这容易被伪造、绕过校验、导致 IP 欺骗。Laravel 的 Request::ip() 在正确配置 TrustProxies 后,内部已做了头字段校验和多级解析(取最左非受信代理 IP),比手写更可靠。

  • 正确做法:确保 AppHttpMiddlewareTrustProxies 已注册在 $middlewareGroups['web']
  • 检查 APP_URL 和部署结构是否匹配(例如 https 被终止在 CDN,但后端没收到 X-Forwarded-Proto: https,可能导致 URL 生成异常)
  • 调试时可用 $request->header('x-forwarded-for') 查看原始头内容,但业务逻辑中仍应统一走 $request->ip()

某些场景下 $request->ip() 仍返回 ::1 或 127.0.0.1

常见于本地开发用 Valet / Homestead / Sail 启动,Nginx 或 caddy 把请求转给了 php-FPM,但未正确设置 fastcgi_param REMOTE_ADDR $remote_addr,或未透传 X-Forwarded-For。这时候即使 Laravel 配置了 trusted proxy,也拿不到上游真实值。

  • Valet 用户:确认 ~/.config/valet/Nginx/*.test 配置里有 fastcgi_param REMOTE_ADDR $remote_addr;
  • docker 环境:检查 Nginx 容器是否将宿主机 IP 加入 proxy_set_header X-Forwarded-For,且 PHP 容器网络模式是否允许识别该头
  • dd($request->server('REMOTE_ADDR'), $request->header('x-forwarded-for')) 对比输出,能快速定位是哪一层丢失了原始 IP

实际 IP 获取这件事,核心不在函数怎么调,而在整个请求链路上每层代理是否规范透传、Laravel 是否被明确告知“谁可信”。漏掉任意一环,Request::ip() 就只是个幻觉。

text=ZqhQzanResources