ThinkPHP 中获取真实调用方 IP 应配置 trusted_proxies 并使用 request()->ip();通过中间件统一提取 UA、Referer、自定义头生成 source_tag;API 身份校验须用 API Key/JWT/OAuth2,禁用 session;日志需过滤敏感头、截断 UA、脱敏公网 IP。

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










