Yii2 ActiveRecord的where数组语法天然防SQL注入,因其底层强制使用PDO预处理并绑定参数;但字符串拼接、动态排序字段、原生SQL未绑定等场景仍存在高风险,须严格白名单校验或参数化处理。

Yii2 本身不是“开箱即用就绝对安全”的框架,而是提供了足够强的工具链——但必须正确使用。用错地方、跳过关键步骤、或在边界场景放松警惕,照样会中招。
ActiveRecord 的 where 数组语法为什么能防 SQL 注入
因为底层强制走 PDO 预处理语句,用户输入永远作为参数绑定,不会拼进 SQL 字符串里。
-
User::findOne(['username' => $input])安全;User::findOne("username = '$input'")危险 - 所有
where()、andFilterWhere()、orFilterWhere()接收数组时都自动参数化,但接收字符串时立刻失效 - 动态字段名(如
orderBy($userSort))不支持参数绑定,必须白名单校验:in_array($userSort, ['created_at', 'price'], true) -
createCommand()手写原生 SQL 时,必须用bindValue(),禁用字符串拼接和bindParam()(引用陷阱)
Html::encode() 不是万能的 XSS 防护
它只适合纯文本输出。一旦内容含富文本(商品描述、评论、后台编辑器),硬编码会破坏结构,而放任不管等于开门揖盗。
- 电商详情页、CMS 文章页等场景,必须用
HtmlPurifier::process($html),配置白名单允许<p>、<strong>、<img>等,剔除<script>、onerror=、javascript: -
HtmlPurifier开销大,别在商品列表页每条记录都调用;建议缓存净化结果,或用 Redis 存purified_html_{$id} - 前端 JS 过滤不可信——攻击者可绕过浏览器直接 POST 原始恶意 HTML,后端仍需净化
- 表单提交的
$_POST['content']必须先净化再入库,否则存储型 XSS 一触即发
CSRF 防护不是配个开关就完事
enableCsrfValidation = true 是起点,不是终点。漏掉任意一环,整个防护就形同虚设。
-
cookieValidationKey必须在config/web.php中显式设置且保密,不能留空或用默认值 - 所有 POST 表单必须包含
Html::csrfInput(),等价于<input type="hidden" name="<code>_csrf</code>" value="<code>xxx</code>"> - JS 发起的
fetch或XMLHttpRequest必须手动把YII_CSRF_TOKEN放进请求体或 header,否则$request->validateCsrfToken()直接返回 400 - GET 请求默认不校验 CSRF,但若用 GET 提交敏感操作(如删除),必须手动加
$request->validateCsrfToken()
最常被忽略的是:动态字段(orderBy、groupBy)、富文本净化缓存、以及 JS 请求里的 CSRF 令牌传递。这三个点,几乎覆盖了线上 Yii2 项目 80% 的真实漏洞来源。


















