白名单过滤必须校验get参数合法性,因直接全量追加会导致缓存失效、日志混乱及敏感信息泄露;应仅保留明确信任的键名,用array_intersect_key()清洗参数,并在控制器中按粒度校验search、type、status等字段。

白名单过滤为什么必须校验GET参数合法性
直接用 $request->query() 全量追加到分页链接,看似省事,实则埋雷:CSRF token、_t 时间戳、前端埋点参数等非业务字段会污染 URL,导致缓存失效、日志混乱、甚至暴露敏感信息。真正的白名单过滤不是“拦 IP”,而是“筛参数”——只保留你明确信任的键名。
如何安全提取并传递合法GET参数
别依赖 $request->all() 或硬编码字段列表,用白名单数组 + array_intersect_key() 最稳妥:
- 定义允许透传的参数键名:
$allowed = ['search', 'type', 'status', 'sort', 'direction']; - 清洗请求参数:
array_intersect_key($request->query(), array_flip($allowed)) - 链式调用:
$products->appends($cleanedQuery)
注意:如果 page 不在白名单里,Laravel 分页器仍能自动处理,无需手动加;但若你自定义了分页参数名(如 p),就得把它加进 $allowed 数组。
控制器里怎么避免漏掉参数校验逻辑
搜索过滤和排序都依赖 GET 参数,但它们的校验粒度不同:
-
search:非空才参与where查询,空字符串或 null 应跳过 -
type和status:必须匹配预设值(如['image', 'pdf']),否则忽略,不报错也不 fallback -
sort:只接受['name', 'size', 'created_at'],非法值默认按created_at排 -
direction:强制转为asc或desc,其他一律设asc
这些判断不能堆在视图里,必须在控制器中完成——否则分页链接生成时就已出错,用户点第二页就丢条件。
模板中回填搜索框值的正确写法
old() 对 GET 请求完全无效,这是 Laravel 的设计事实,不是 bug。正确做法是直接读 query:
<input name="search" value="{{ request('search') ?? '' }}">
别用 {{ old('search') }},它只对 POST 表单生效;也别在控制器里 withInput(),那只会往 session 写一堆无用数据。
真正容易被忽略的是:当用户从非搜索页跳转过来(比如带参的分享链接),request('search') 依然能取到值,而 old() 永远为空——这决定了回填逻辑必须面向 URL,而非 session。











