Yii2需配置ipHeaders和trustedHosts才能安全获取真实IP;UA需防XSS、合理存储并结合多维度风控;Yii3需手动解析头并自行校验代理IP。

Yii2 中怎么安全获取客户端真实 IP
直接用 $request->getUserIP() 很容易拿错,尤其在有反向代理(Nginx、CDN、SLB)的场景下,默认只读 REMOTE_ADDR,实际拿到的是上一跳代理的 IP,不是用户真实出口 IP。
必须显式配置可信代理列表,否则 getUserIP() 会忽略 X-Forwarded-For 或 X-Real-IP 等头。Yii2 默认不信任任何代理,这是安全设计,但也是最常被忽略的前提。
- 在
config/web.php的request组件中加'ipHeaders' => ['X-Forwarded-For', 'X-Real-IP'] - 同时必须设置
'trustedHosts' => ['10.0.0.0/8', '192.168.0.0/16', '172.16.0.0/12'](填你实际的内网代理段) - 如果用云厂商 SLB 或 CDN,要查清它转发时用的头名(比如腾讯云用
Tencent-Cloud-Real-IP),并加进ipHeaders - 别把公网 IP 写进
trustedHosts,否则攻击者伪造头就能绕过
Yii2 获取 User-Agent 的正确姿势
$request->getUserAgent() 本身没问题,但它只是原样返回 $_SERVER['HTTP_USER_AGENT'],不校验、不清理、不缓存。真正要注意的是后续怎么用它。
- 永远不要直接输出到 HTML,避免 XSS(比如 UA 里带
<script>) - 做设备识别时,别只靠字符串包含判断,用现成库如
sinergi/browser-detector,或至少用正则匹配关键特征(/Mobile\/\w+/i判手机,/Edg\//i判 Edge) - 注意移动端 UA 可能极长(超 4KB),MySQL 存字段别用
VARCHAR(255),建议TEXT或截断前 512 字符 - 某些爬虫会伪造 UA,单靠 UA 不足以做风控,需结合行为、IP、请求频率综合判断
Yii3 的 ServerRequestInterface 怎么取 IP 和 UA
Yii3 彻底转向 PSR-7,不再有 getUserIP() 这种封装方法,所有信息都得从 ServerRequest 对象里手动解析,自由度高,但出错率也高。
- IP 要自己读头:先检查
$request->getHeaderLine('X-Forwarded-For'),再 fallback 到$request->getServerParams()['remote_addr'] - 必须自己实现可信代理校验逻辑——Yii3 不提供
trustedHosts配置,得自己写 if 判断来源 IP 是否在白名单 - UA 直接用
$request->getHeaderLine('User-Agent'),注意它可能为空字符串,不是null - 别忘了头名大小写不敏感,但 PSR-7 规范要求
getHeaderLine()自动处理,不用手写strtolower()
常见错误现象和调试方法
线上经常看到 IP 固定为 127.0.0.1 或 UA 为空,基本都是配置没生效或环境理解错。
- 用
var_dump($request->getHeaders())和var_dump($request->getServerParams())对比看哪些头实际到了 PHP 层 - Nginx 配置里漏了
proxy_set_header X-Real-IP $remote_addr;,会导致头根本没传进来 - Docker 容器里
REMOTE_ADDR是容器网桥地址(如172.18.0.1),不是宿主机 IP,得靠头传递 - 测试时用
curl -H "X-Forwarded-For: 1.2.3.4" http://localhost模拟,别只信浏览器直连结果
IP 和 UA 这两个值,看着简单,但每层网络设备、每个中间件、每次部署变更都可能悄悄改掉它们。真要稳,就得每层都验证,不能只信框架默认行为。










