如何在Nginx中无需自定义location阻止敏感静态文件访问
解决方案
问题根源在于location /中的try_files $uri $uri/ /index.php?$query_string;规则:当请求的文件(比如php-fpm.conf)实际存在时,Nginx会直接返回该文件内容,不会继续执行到/index.php的转发逻辑。
要避免敏感文件被直接访问,且无需按后缀配置deny规则,最佳方案是让所有非指定静态资源目录的请求,无论文件是否存在,都直接转发到PHP统一处理,具体配置调整如下:
配置修改步骤
- 保留原有静态资源目录的location规则(匹配
images、js等目录),这类正则location优先级更高,会优先处理合法静态资源请求。 - 新增一个命名location
@php,统一封装PHP转发的逻辑;同时修改根location /的规则,直接将非静态资源请求导向这个命名location。
调整后的核心配置片段:
# 保留原静态资源规则不变 location ~ ^/(images|javascript|js|css|fonts|static|assets)/ { root /legacy/app/; expires 30d; add_header Cache-Control public; access_log off; } # 新增命名location,统一处理PHP请求 location @php { root /legacy/app; fastcgi_pass 127.0.0.1:9000; fastcgi_read_timeout 600s; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; # 强制指定执行脚本为index.php,实现统一路由 fastcgi_param SCRIPT_FILENAME $document_root/index.php; include .nginx/fastcgi.conf; } # 修改根location,直接转发所有非静态资源请求到@php location / { try_files @php; } # 保留原.php后缀的location(可选),处理直接访问PHP文件的场景 location ~ \.php$ { root /legacy/app; fastcgi_pass 127.0.0.1:9000; fastcgi_read_timeout 600s; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; }
原理说明
- 静态资源目录的正则location优先级高于根
location /,因此合法静态资源会被正常返回,不影响原有静态资源访问。 - 所有其他请求(包括存在的
.conf/.md敏感文件、不存在的路径)都会直接进入@php,由index.php统一处理,不会直接返回服务器上的敏感文件。 - 原有的
.php后缀location可保留,用于处理直接访问PHP文件的场景,和@php逻辑不冲突。
简化版替代方案
如果不需要过多灵活性,也可以直接修改根location /的try_files规则,跳过对$uri的存在性检查:
location / { try_files /index.php?$query_string =404; }
这种方式更简洁,但需要确保/index.php文件存在,推荐优先使用命名location的方案。
内容的提问来源于stack exchange,提问作者DmitrySemenov
相关产品推荐
相关产品推荐

