PHP文件验证规则有哪些

wen PHP项目 1

本文目录导读:

PHP文件验证规则有哪些

  1. 文件上传错误代码验证($_FILES[”error”])
  2. 文件大小验证
  3. 文件类型验证(MIME 类型)
  4. 文件扩展名验证
  5. 重写文件名(防止路径穿越与冲突)
  6. 图片内容验证(针对图片)
  7. 其他安全与业务规则
  8. 完整的安全验证流程(推荐顺序)
  9. 常见误区和陷阱

在 PHP 中进行文件验证(通常指文件上传时的验证),主要目的是确保上传的文件安全、有效且符合预期,以下是常见且必须的 PHP 文件验证规则,通常按顺序执行:

文件上传错误代码验证($_FILES[”error”])

这是第一道防线,PHP 会根据上传是否成功自动填充一个错误代码。

  • UPLOAD_ERR_OK(值 0):无错误,文件上传成功。
  • UPLOAD_ERR_INI_SIZE(1):文件超过 php.iniupload_max_filesize 限制。
  • UPLOAD_ERR_FORM_SIZE(2):文件超过 HTML 表单中 MAX_FILE_SIZE 指定的大小。
  • UPLOAD_ERR_PARTIAL(3):文件只有部分被上传(网络问题)。
  • UPLOAD_ERR_NO_FILE(4):没有上传文件(用户未选择)。
  • UPLOAD_ERR_NO_TMP_DIR(6):缺少临时文件夹(服务器环境问题)。
  • UPLOAD_ERR_CANT_WRITE(7):写入磁盘失败。

示例代码:

if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
    die('上传失败,错误代码:' . $_FILES['file']['error']);
}

文件大小验证

防止用户上传过大文件撑爆服务器。

  • PHP 配置限制(服务器端): upload_max_filesizepost_max_size
  • 代码验证(推荐): 使用 $_FILES['file']['size'] 进行校验。
$maxSize = 2 * 1024 * 1024; // 2MB
if ($_FILES['file']['size'] > $maxSize) {
    die('文件大小不能超过 2MB');
}

文件类型验证(MIME 类型)

注意: 不能仅依赖 $_FILES['file']['type'],因为这个值由客户端(浏览器)控制,极易被篡改,不安全的做法如下:

// ❌ 不安全:客户端可以随意修改这个值
if ($_FILES['file']['type'] !== 'image/jpeg') {
    die('只允许 JPEG 图片');
}

正确做法:使用服务器端函数检测。

  • 图片文件: getimagesize()exif_imagetype()
  • 通用文件: finfo_open()finfo_file()(基于文件魔数魔术字节,更可靠)。
// ✅ 安全:使用服务器端真实文件检测
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
$allowedTypes = ['image/jpeg', 'image/png'];
if (!in_array($mimeType, $allowedTypes)) {
    die('只允许 JPEG 或 PNG 图片');
}

文件扩展名验证

防止用户上传 shell.php 并伪装成图片(双重校验)。

$extension = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
$allowedExts = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($extension, $allowedExts)) {
    die('不允许的文件扩展名');
}

重写文件名(防止路径穿越与冲突)

用户上传的文件名可能包含恶意字符(如 ../../etc/passwd)或中文字符。永远不要使用原始文件名保存到磁盘。

  • 方案: 生成唯一文件名(UUID、时间戳 + 随机数)。
  • 安全存储: 将文件移出 document_root(网站根目录),或设置 http://example.com/uploads/ 目录下 .htaccess 禁止执行 PHP。
$newFileName = uniqid() . '.' . $extension; // 如 61f8a3b1c2d3e.jpg
if (!move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $newFileName)) {
    die('文件保存失败');
}

验证(针对图片)

如果只允许图片,除了 MIME 检测,还需验证图片完整性。

$imageInfo = getimagesize($_FILES['file']['tmp_name']);
if ($imageInfo === false) {
    die('文件不是有效的图片');
}
// 可以继续检查宽度、高度等
if ($imageInfo[0] > 2000 || $imageInfo[1] > 2000) {
    die('图片尺寸过大');
}

其他安全与业务规则

  • 目录权限检查: 确保 uploads/ 目录可写,且不允许执行。
  • 文件数量限制: 防止用户恶意批量上传。
  • 黑名单检测: 禁止包含 PHP 代码片段(如 <?php)在文件内容中(用于简易文本验证)。
  • SVG 文件警告: SVG 可能包含 JavaScript(XSS 攻击),需严格消毒或禁用。
  • 临时文件清理: 如果未用 move_uploaded_file(),临时文件会在脚本结束后自动删除。

完整的安全验证流程(推荐顺序)

  1. 检查 $_FILES['file']['error'] 是否为 UPLOAD_ERR_OK
  2. 检查文件大小 $_FILES['file']['size'] 是否符合限制。
  3. 使用 finfo 检测真实的 MIME 类型。
  4. 检查文件扩展名(作为辅助手段)。
  5. 如果是图片,使用 getimagesize() 验证图片完整性。
  6. 生成唯一文件名(避免原有名称)。
  7. 使用 is_uploaded_file() + move_uploaded_file() 移动文件(确保是上传的文件)。

常见误区和陷阱

  • 🚫 不要使用 $_FILES['file']['type'] 作唯一判断。
  • 🚫 不要使用黑名单扩展名(如 .php3.phtml 仍可能被解析)。
  • 🚫 不要允许 .htaccess.user.ini 上传。
  • ✅ 推荐:上传目录关闭 PHP 执行权限(Nginx 中 location ~ \.php$ { deny all; })。
  • ✅ 推荐:将文件存储到非 Web 可访问目录,通过 PHP 代理脚本读取并提供下载。

这些规则不仅用于上传,也适用于脚本中处理文件时的基本验证逻辑。

抱歉,评论功能暂时关闭!