yii生产环境需强制启用csrf防护(enablecsrfvalidation=true且cookievalidationkey为32+字符随机密钥)、禁用unserialize()、富文本输出必用htmlpurifier过滤、会话cookie须设httponly/secure/samesite,并禁止nginx直接访问vendor等敏感目录。

Yii框架本身安全机制比较扎实,但默认配置不等于生产就绪。很多漏洞不是框架缺陷,而是开发者没关掉调试、没设密钥、没过滤输入,或者把危险函数留在代码里没清理。
enableCsrfValidation 必须设为 true,且 cookieValidationKey 不能空
CSRF 防护开关默认是关的,enableCsrfValidation 不显式设为 true,所有 POST 表单都裸奔。光开这个还不够——它依赖 cookieValidationKey 签名生成令牌,这个值一旦为空或用默认模板值,攻击者就能伪造令牌。
- 检查
config/web.php或环境配置文件(如environments/prod/frontend/config/main-local.php),确认'cookieValidationKey' => '一长串随机字符'已设置,长度建议 ≥32 字符,可用bin/yii serve启动时提示的命令生成 - 表单必须包含
Html::csrfInput();AJAX 提交需手动在请求头加X-CSRF-Token: = Yii::$app->request->getCsrfToken() ?> - GET 请求不校验 CSRF,但若用 JS 发起 POST 到非表单接口(如
fetch('/api/order', {method: 'POST'})),后端仍要调用$request->validateCsrfToken()显式验证
unserialize() 是反序列化漏洞的直接入口,必须全局清除
Yii 应用若存在 unserialize($_GET['data']) 或类似调用,就等于给攻击者开了远程代码执行的后门。PHP 7.4+ 虽支持 allowed_classes 参数,但不如直接不用来得干净。
- 用
grep -r "unserialize(" . --include="*.php"全局搜索,重点检查缓存读取、会话反解、第三方扩展(如旧版 Redis 封装) - 替换方案统一用
json_decode($input, true),并配合严格类型校验:is_array($data) && isset($data['id'], $data['type']) - 实在无法避免(如兼容老协议),必须加白名单正则校验:
if (!preg_match('/^O:\d+:"(SafeConfig|UserPrefs)":/', $input)) { throw new InvalidArgumentException(); }
HtmlPurifier 不是可选项,是富文本输出的强制要求
Html::encode() 只能防纯文本 XSS,一旦页面要渲染用户提交的带格式内容(商品描述、后台编辑器、评论),就必须上 HtmlPurifier。它基于白名单过滤,能剔除 <script></script>、onerror=、javascript: 等全部危险成分。
- 不要在高频接口(如列表页、搜索页)每次调用
HtmlPurifier::process(),性能损耗明显;应缓存净化结果,例如用Yii::$app->cache->set("purified_{$hash}", $cleanHtml, 86400) - 白名单规则要收敛:只允许
p、strong、ul、li等基础标签,禁用style属性和class(除非你明确控制 CSS 类名) - 前端 JS 过滤无效——用户绕过前端直接发原始 HTML 到后端,后端照样得处理;所有输出到视图的变量,只要来源含用户输入,就必须走净化或转义
会话 Cookie 必须设 httpOnly、secure、sameSite
会话劫持往往从 Cookie 泄露开始。session 组件的 cookieParams 若没配全,JS 可读取、HTTP 可传输、跨站可携带,等于把钥匙挂门口。
- 配置示例:
'cookieParams' => ['httpOnly' => true, 'secure' => YII_ENV_PROD, 'sameSite' => 'Lax'];secure在生产环境必须为true,否则 HTTPS 下 Cookie 不会被发送 - 敏感操作(登录、改密、支付)后必须调用
Yii::$app->session->regenerateID(true),防止会话固定 - 别依赖 IP 绑定做会话校验——NAT、移动网络下 IP 经常变,容易误踢用户;真要增强,可用 User-Agent 指纹 + 登录时间窗口组合判断异常
最易被忽略的是 Nginx 层面的防护:vendor、runtime、config 目录必须禁止 HTTP 直接访问,.htaccess 在 Apache 下有效,但在 Nginx 中得靠 location ~ ^/(vendor|runtime|config)/ + deny all 显式拦截,否则源码泄露风险一直存在。











