realpath() 是路径校验关键一环,先规范化路径(消除./、../、符号链接),再验证是否在可信根目录内,最后安全创建;它不替代mkdir,而是其必需前置步骤。

用 realpath() 校验路径安全,核心是**先规范化、再验证、后操作**。它不是 mkdir 的替代品,而是 mkdir 前必须走的安全前置步骤——尤其当路径含用户输入、相对符号或拼接变量时。
为什么 realpath 是路径校验的关键一环
mkdir() 本身不检查路径是否“合法”或“指向预期位置”。比如传入 ../../etc 或 /var/www/../tmp,它可能直接在你没意识到的地方建目录。realpath() 能把这类路径展开成绝对、无歧义的真实路径,并自动剔除 /./、/../ 和符号链接,同时在路径不存在时返回 false,帮你提前拦截风险。
注意:realpath() 要求所有中间目录都存在且当前脚本有执行权限(x),否则也返回 false —— 这反而是好事,说明路径不可达,不该贸然 mkdir。
安全创建目录的三步闭环流程
不要跳过任何一步:
-
第一步:用 realpath() 获取规范绝对路径
即使你传的是相对路径或带..的路径,realpath() 也会把它转成类似/var/www/uploads/2024/11这样的唯一形式。 -
第二步:比对前缀,防止越界
拿到 realpath 后,检查它是否以你的“可信根目录”开头。例如你只允许在/var/www/myapp/data下建目录,那就用str_starts_with($realPath, '/var/www/myapp/data')确认。 -
第三步:确认目标不存在且父级可写,再 mkdir
用is_dir($realPath)判断是否已存在;若不存在,再调用mkdir($realPath, 0755, true)创建——第三个参数true确保多级目录一次到位。
常见错误写法与修正示例
❌ 错误:直接拼接用户输入 + mkdir
$userDir = $_GET['dir']; // 如传入 "..%2Fetc%2Fshadow"
mkdir("/var/www/uploads/{$userDir}"); // 危险!可能建到系统目录
✅ 正确:先 realpath 规范,再锚定根目录
$base = '/var/www/uploads';
$userInput = basename($_GET['dir']); // 先剥离路径成分
$target = $base . DIRECTORY_SEPARATOR . $userInput;
$realPath = realpath($target);
<p>if ($realPath === false) {
die('路径无效或不可访问');
}
if (!str_starts_with($realPath, $base)) {
die('禁止访问外部路径');
}
if (!is_dir($realPath)) {
mkdir($realPath, 0755, true);
}</p>
Windows 和跨平台注意事项
realpath() 在 Windows 上会把正斜杠转成反斜杠,并补全盘符(如 C:\var\www),不影响逻辑判断。但要注意:
• 权限掩码(如 0755)在 Windows 下被忽略,不用纠结;
• 路径非法字符(: * ? " |)需在调用 realpath 前用正则过滤,否则 realpath 直接返回 false,且不报具体原因;
• 建议统一用 DIRECTORY_SEPARATOR 拼接路径,避免硬写 / 或 \。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











