接着帖子里第三步往下补:目录遍历优先用 SPL 迭代器,权限管理的核心不是 chmod 而是「禁执行」。
目录遍历的三种正确姿势,别混用:
- 单层、要完整条目 →
scandir(),务必跳过.和..; - 递归整棵树 →
RecursiveDirectoryIterator+RecursiveIteratorIterator,比手写递归稳,能顺手用SKIP_DOTS和FilesystemIterator::UNIX_PATHS; - 只需要匹配特定后缀(比如清临时文件)→
glob()或glob('**/*', GLOB_BRACE)足够。
手写递归最大的坑是符号链接死循环——目录里有个链回上层的 symlink,递归直接跑飞。用 is_link() 判断,或者 SPL 那边加 RecursiveIteratorIterator::CHILD_FIRST 配合自己过滤。另外任何路径都先过 realpath() 校验,防止 ../../etc 这类穿越。
权限管理部分,记住一句:上传目录要「能写」但绝不能「能被当脚本跑」。目录 755、文件 644,所有者是 PHP-FPM 运行用户(www/www-data),永远不要 777。更关键的是在 Web 服务器层直接断掉执行:
- Nginx:
location ~* ^/uploads/.*\.(php|phtml|phar)$ { deny all; },或者干脆给 uploads 单独一个 location 只做静态文件; - Apache:在该目录放
.htaccess写php_flag engine off(或RemoveHandler .php)。
光靠上传白名单挡不住 .htaccess 被覆盖、或解析漏洞这类情况,所以「白名单 + 服务器层禁执行 + 目录不可解析」是三件套,缺一不可。
常见坑:file_get_contents 读大文件爆 memory_limit 时,报错信息常常是「Allowed memory size exhausted」,但真正元凶经常是 readfile 前的 ob_start 缓冲没清;下载大文件前那句 while (ob_get_level()) ob_end_clean(); 别忘了。
正式会员
认证极客






