csrf防护需显式启用enablecsrfvalidation并联动令牌生成、前端嵌入、后端验证;cookievalidationkey须保密;表单必含csrfinput;xss须用htmlpurifier白名单过滤;sql注入需白名单校验动态字段并严格参数绑定;http安全头与cookie属性须手动配置。

CSRF 防护必须开,且不能只靠配置
Yii2 的 CSRF 防护默认是关的,enableCsrfValidation 必须显式设为 true,否则所有表单都裸奔。但光配这一项远远不够——它只是开关,真正起作用依赖三个联动环节:令牌生成、前端嵌入、后端验证。
-
cookieValidationKey必须设置且保密,它是 CSRF 令牌签名的基础;留空或用默认值等于形同虚设 - 表单里必须有
Html::csrfInput()或手动写<input type="hidden" name="<?= $request->csrfParam ?>" value="<?= $request->getCsrfToken() ?>">,漏掉就直接 400 - 非
POST表单(比如带method="get"的搜索)不会自动校验,但若用 JS 发起fetch或XMLHttpRequest提交POST,也得手动把YII_CSRF_TOKEN放进请求头或 body,否则控制器里$request->validateCsrfToken()会失败
XSS 输出转义不能只靠 Html::encode()
对纯文本内容,Html::encode($userInput) 足够安全;但电商场景中,商品描述、富文本评论、后台编辑器输出等,往往需要保留部分 HTML 标签(如 <p></p>、<strong></strong>),这时硬编码会把整个结构搞成乱码,而完全不处理又埋下 XSS。
- 必须用
HtmlPurifier::process($html)替代简单转义,它基于白名单过滤,能剔除<script></script>、onerror、javascript:等危险成分 - 注意性能:
HtmlPurifier解析开销大,别在高频接口(如商品列表页)里每次调用;建议缓存净化结果,或用 Redis 存净化后的 HTML - 别信前端过滤——用户绕过 JS 校验直接发请求,后端照样得处理原始输入;所有输出到页面的变量,只要来源含用户提交,就得走净化或转义
SQL 注入防护不是“用了 ActiveRecord 就万事大吉”
Active Record 默认用 PDO 预处理,确实挡住绝大多数拼接式注入;但开发者常在边界处翻车:比如动态字段排序、条件字段名、原生 SQL 拼接、或用 createCommand() 手写查询时图省事直接插变量。
- 排序字段必须白名单校验:
if (!in_array($orderBy, ['name', 'price', 'created_at'])) { throw new BadRequestHttpException(); },绝不能直接拼进ORDER BY :orderBy - 原生查询务必用参数绑定:
createCommand("SELECT * FROM product WHERE status = :status")->bindValue(':status', $status),而不是"WHERE status = '$status'" - DAO 查询构建器里,
andFilterWhere()和andFilterWhere()是安全的,但addSelect()或from()如果传入用户可控字符串,一样会出问题
HTTP 安全头和 Cookie 设置容易被忽略
CSRF 和 XSS 防护再严,如果响应头没设好,攻击面依然敞开。这些配置不在 Yii 主逻辑里,得手动加在入口文件或中间件里,上线前极易遗漏。
- 在
web/index.php开头加:header('X-Content-Type-Options: nosniff')、header('X-Frame-Options: DENY')、header('X-XSS-Protection: 1; mode=block') -
session.cookie_httponly和session.cookie_secure要在php.ini或ini_set()中开启,否则 JS 可读取 session cookie,XSS 成功率飙升 - 生产环境必须启用
Strict-Transport-Security(HSTS),否则 HTTPS 可被降级劫持,CSRF Token 和登录态都可能泄露
安全配置不是一次打钩就完事的事。比如 cookieValidationKey 换了会导致所有现有会话失效;HtmlPurifier 规则改了可能误杀合法标签;HSTS 头一旦加上,浏览器会强制记很久——这些变动都要测回归,不能只看“功能跑通”。










