答案:必须用strtolower(pathinfo($filename, pathinfo_extension))提取并小写标准化扩展名,再用in_array()比对硬编码小写白名单;仅后缀校验不安全,须配合finfo_file()验证真实mime类型及权限隔离。

需要在PHP中判断用户上传的文件后缀是否属于预设的安全列表,防止恶意文件(如.php、.exe)绕过前端校验被保存到服务器。
获取并标准化文件后缀
使用 pathinfo() 提取扩展名,并转为小写避免大小写绕过:$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
这一步必须做。Windows系统下上传 shell.PHP 会被当作合法后缀,不转小写会导致白名单比对失败。
用in_array()快速比对白名单
方法一:基础白名单校验
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'pdf'];<br>
if (!in_array($ext, $allowed)) {<br>
die('不支持的文件类型');<br>
}
注意:白名单数组必须全小写,且不能含点号(如 '.jpg'),否则 in_array() 比对会失败。
用正则精确匹配带边界限制的后缀
方法二:防御更严的正则方式
第一步:构造白名单字符串 → 第二步:拼接成锚定正则 → 第三步:执行匹配
$allowed = ['jpg', 'jpeg', 'png'];<br>
$pattern = '/^('.implode('|', array_map(function($e) { return preg_quote($e, '/'); }, $allowed)).')$/i';<br>
if (!preg_match($pattern, $ext)) {<br>
die('非法后缀');<br>
}
这个正则加了 ^ 和 $ 锚点,能杜绝 php.jpg.txt 这类多点后缀的混淆攻击;preg_quote() 防止白名单里出现特殊字符(如 .xml 中的点)破坏正则结构。
结合MIME类型二次校验(推荐增强)
仅靠后缀不可信,需配合 finfo_file() 检查真实类型:
$finfo = finfo_open(FILEINFO_MIME_TYPE);<br> $mimeType = finfo_file($finfo, $_FILES['file']['tmp_name']);<br> finfo_close($finfo);
常见图片MIME应为 image/jpeg、image/png 等;PDF为 application/pdf。若 $mimeType 与后缀明显不符(如后缀是.jpg但MIME是text/plain),直接拒绝。
这一步要求服务器启用 fileinfo 扩展,未启用时 finfo_open() 会报错,需提前检查。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











