PHP 7.4 文件包含白名单过滤需硬编码允许文件名并用 in_array($page, $allowed_files, true) 严格校验,结合 DIR 拼接路径、强制添加 .php 后缀及 Web 服务器目录禁用实现纵深防御。

PHP 7.4 中实现文件包含(include/require)的白名单过滤,核心原则是:**不依赖用户输入拼接路径,不信任任何外部参数,只允许预定义的、绝对安全的文件名列表**。下面给出简洁、实用、符合安全实践的写法。
明确白名单数组,限定可包含的文件名
把允许包含的文件名(不含扩展名或带扩展名均可,但需统一)硬编码在数组中,避免从 URL、POST 或 GET 动态构造文件名。
⚠️ 注意:白名单必须是完整文件名(如'header' 或 'header.php'),不能只过滤目录或后缀。
示例:
$allowed_files = [
'header',
'footer',
'sidebar',
'contact_form'
];
严格校验用户传入的参数是否在白名单内
用 in_array() 判断,且开启严格模式(第三个参数设为 true),防止类型混淆绕过(如 0 == 'header' 这类弱比较漏洞)。
立即学习“PHP免费学习笔记(深入)”;
推荐写法:
$page = $_GET['page'] ?? '';
if (!in_array($page, $allowed_files, true)) {
die('Access denied');
}
// 安全包含
include __DIR__ . '/templates/' . $page . '.php';
补充建议:路径隔离 + 扩展名强制 + 目录限制
进一步加固,可组合以下措施:
-
固定基础目录:使用
__DIR__或dirname(__FILE__)拼接,避免相对路径穿越(如../../etc/passwd) -
强制添加扩展名:不依赖用户传入的扩展名,统一加
.php(或.inc),防止包含日志、上传文件等非预期类型 -
禁用动态解析:确保目标目录不在 Web 可访问路径下,或通过 Web 服务器配置禁止该目录执行 PHP(如 Nginx 的
location ~ ^/templates/ { deny all; })
不推荐的写法(常见误区)
以下方式看似“过滤”,实则极易被绕过,不要使用:
-
str_replace(['../', '..\'], '', $_GET['page'])—— 双写、编码、截断可绕过 -
preg_match('/^[a-z]+.php$/', $_GET['page'])—— 未锚定开头结尾,或忽略大小写、Unicode 等问题 -
basename($_GET['page']) === $_GET['page']—— 仅防路径遍历,不防文件名本身恶意(如phpinfo.php若在白名单外仍危险)



















