ThinkPHP 中获取真实调用方 IP 应配置 trusted_proxies 并使用 request()->ip();通过中间件统一提取 UA、Referer、自定义头生成 source_tag;API 身份校验须用 API Key/JWT/OAuth2,禁用 session;日志需过滤敏感头、截断 UA、脱敏公网 IP。
如何在 ThinkPHP 中获取真实调用方 IP
直接取
大概率不准——反向代理、CDN、负载均衡会把它变成网关或本机地址。必须结合
或
等头字段,但不能无条件信任。
ThinkPHP 5.1+ 内置的
默认已做基础代理处理,但默认只信任
和
,线上部署时若没配可信代理列表,依然会拿错。
在
中显式配置
(按实际内网段填)
确保 Nginx 或 SLB 转发时设置了
,且不伪造该头
避免前端直接透传用户可控的
,否则可被恶意覆盖
用中间件统一记录调用来源信息
别在每个接口里手写日志逻辑。ThinkPHP 的中间件是唯一合理位置:它能拦截所有请求,在进入路由前拿到完整上下文,也方便后续关联 trace_id。
新建中间件
,在
里提取关键字段:
立即学习
“
PHP免费学习笔记(深入)
”;
用
判断是否为小程序、APP、curl 或浏览器
检查
是否为空或来自可信域名(防恶意 Referer 注入)
若调用方带了自定义头如
或
,直接取值并校验格式(比如是否为 UUID 或预设枚举)
把组合后的来源标识(如
)存进
,供后续控制器使用
第三方调用的身份校验必须独立于 session
接口调用方不是浏览器,没有 cookie 和 session 上下文。靠
或
做识别纯属误用,极易失效或被复用。
真正可行的身份凭证只有三类:API Key、JWT、OAuth2 Access Token。ThinkPHP 本身不内置鉴权,得自己接或用扩展:
API Key 推荐放在请求头
,服务端查白名单表 + 频控 + 过期时间
JWT 必须校验
(签发方)、
(受众)、
,别只 decode 不 verify;用
而非手动解析
若用
类扩展,请确认它是否支持无 state 的 token 模式——很多封装默认强依赖 session
日志中保留来源链路但避免敏感泄露
记录调用来源是为了排查问题,不是为了存全量请求头。一不留神就把
、
、
打进日志,等于主动送密钥。
写日志前务必过滤:
用
剔除高危头
对
做截断(比如只留前 128 字符),防止超长 UA 导致日志轮转异常
IP 地址脱敏处理,如
(内网 IP 可不脱敏,但需明确标注)
如果用了分布式追踪(如 SkyWalking),优先用 trace_id 关联,而非在每条日志里重复拼来源字符串
最麻烦的永远不是怎么记,而是谁有权看、保留多久、导出时是否自动过滤——这些不在代码里,但在上线前就得定死规则。
$_SERVER['REMOTE_ADDR']X-Forwarded-ForX-Real-IPrequest()->ip()127.0.0.1::1config/app.php'trusted_proxies' => ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']proxy_set_header X-Real-IP $remote_addr;X-Forwarded-ForApp\Middleware\TrackSourcehandle()$request->header('user-agent')$request->header('referer')X-App-IDX-Client-Type"wxapp-v2.3.1@10.20.30.40"$request->withAttr('source_tag', ...)session_id()think\SessionAuthorization: ApiKey xxxxxissaudexpfirebase/php-jwtthink-authAuthorizationCookieX-API-Keyarray_diff_key($headers, array_flip(['authorization', 'cookie', 'x-api-key']))user-agentsubstr_replace($ip, 'xxx', -3)