thinkphp的runtime目录必须既禁止web直接访问又允许php进程写入,否则将导致敏感信息泄露(如日志中含数据库密码、token)或服务无法启动(因mkdir失败、白屏)。

runtime 目录不能被 Web 服务器直接访问,也必须对 PHP 进程可写——这两点没同时满足,不是日志丢失、缓存不生成,就是敏感信息泄露。
为什么 runtime 目录既不能被访问又必须可写
ThinkPHP 把日志、缓存、模板编译、路由映射等全写进 runtime,这些文件一旦通过 URL(比如 /runtime/log/202405/01.log)能直接下载,数据库密码、SQL 语句、用户 token 全暴露;但若 Web 进程(如 www-data)没写权限,又会报 mkdir(): Permission denied 或白屏,根本起不来。
-
runtime绝对不能放在 Web 根目录下(例如 Nginx 的root或 Apache 的DocumentRoot所指路径内) - 它必须由 Web 进程用户(非
root)拥有,且子目录需递归可写 - 日志内容本身也要脱敏,但这是第二道防线;第一道是「路径隔离 + 权限控制」
Nginx 下彻底屏蔽 runtime 访问的 location 配置
只写 deny all 不够,正则匹配顺序、隐藏文件、无后缀路径都可能绕过。以下配置必须放在 server 块中,且在 location ~ \.php$ 之前:
location ^~ /runtime/ {
deny all;
}
location ~ ^/runtime/.*\.(log|txt|trace|swp|swo|lock|php)$ {
deny all;
}
location = /runtime {
return 403;
}
-
^~ /runtime/优先级最高,覆盖所有以/runtime/开头的请求,包括/runtime/自身和子路径 - 第二个正则补漏:防止攻击者用
/runtime/xxx.php或/runtime/.git/config绕过 - 单独加
location = /runtime是防目录遍历或空路径试探,返回明确 403 而非 404(避免暴露目录存在)
Apache 中比 .htaccess 更可靠的防护方式
.htaccess 在多数生产环境默认禁用,或因容器、CI/CD 流程被覆盖而失效。更稳的方式是在虚拟主机配置里硬限制:
<directory>
Require all denied
</directory>
- 路径必须写绝对路径,且与实际部署位置一致(别抄错成
/var/www/html/runtime却实际在/opt/app/runtime) - 确认
AllowOverride None时.htaccess完全无效,所以别依赖它 - 如果
runtime已移出 Web 根目录(推荐做法),这一步其实可以跳过——因为压根没路由映射到它
给 runtime 设权限时最容易踩的三个坑
安全和可用性失衡,往往就毁在这几步:
- 用
chmod -R 777 runtime—— 文件权限失控,扫描工具直接标高危,且无法阻止 PHP 写入恶意文件 - 只改了
runtime目录权限,没递归处理子目录(如runtime/log、runtime/cache),导致部分子目录仍不可写 - 运行用户设错了:Ubuntu 默认是
www-data,CentOS 是nginx或apache,用ps aux | grep php-fpm确认实际用户,别凭经验瞎猜
最稳妥的操作是:chown -R www-data:www-data runtime + find runtime -type d -exec chmod 755 {} \; + find runtime -type f -exec chmod 644 {} \;,再验证日志是否正常生成。
真正麻烦的从来不是配置几行规则,而是把「Web 不可见」和「PHP 可写」这对矛盾,在具体部署路径、用户权限、服务器配置三者之间对齐。少对齐一环,问题就藏在看似正常的日志里,等被扫出来才后悔。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











