关键在于用internal指令配合rewrite和alias,实现伪静态URL对外友好、真实PHP资源仅限内部跳转访问,彻底阻断外部直连,提升安全性。

要通过 Nginx 实现既支持伪静态 URL,又严格保护真实资源不被直接访问,关键不是单纯用 rewrite 重写,而是配合 internal 指令构建“仅内部跳转”的访问通道。下面用一个典型场景——隐藏后台接口文件、防止 .php 资源被恶意直连——来实战演示完整逻辑。
一、明确目标:伪静态 URL 与真实资源分离
假设网站对外提供如下友好 URL:
-
/user/profile/123→ 实际由/api/user.php?id=123处理 -
/post/detail/456→ 实际由/api/post.php?id=456处理
但必须确保:用户无法直接请求 /api/user.php?id=123 或 /api/*.php,否则绕过权限校验或暴露内部结构。
二、核心配置:用 internal 阻断外部直达,rewrite 控制入口
在 server 块中添加如下配置:
location /api/ {
internal; # ← 关键!仅允许内部 rewrite 跳转访问,拒绝所有外部请求
alias /var/www/html/api/;
}
<p>location ~ ^/user/profile/(\d+)$ {
rewrite ^/user/profile/(\d+)$ /api/user.php?id=$1 last;
}</p><p>location ~ ^/post/detail/(\d+)$ {
rewrite ^/post/detail/(\d+)$ /api/post.php?id=$1 last;
}</p><h1>额外防护:禁止直接访问 .php 文件(除 internal 允许的路径外)</h1><p>location ~ .php$ {
deny all;
}说明:
-
internal必须作用于/api/这个 location,且需搭配alias(不能用root),否则内部跳转会失败 -
rewrite ... last触发后,Nginx 会重新匹配 location,此时命中/api/区块,并因internal判定为合法内部请求 - 外部用户尝试访问
https://example.com/api/user.php?id=123会直接返回 404(或 403,取决于 internal 行为)
三、进阶技巧:统一入口 + 权限前置校验
若需在跳转前做统一鉴权(如检查 Cookie、Token),可将 rewrite 改为 return + error_page 配合:
location ~ ^/(user|post)/ {
# 先校验权限(示例:检查 X-Auth-Token)
if ($http_x_auth_token = "") {
return 401 "Unauthorized";
}
<pre class="brush:php;toolbar:false;"># 校验通过后,内部重定向到 api 目录
rewrite ^/user/profile/(\d+)$ /_internal_user_profile/$1 break;
rewrite ^/post/detail/(\d+)$ /_internal_post_detail/$1 break;
return 404;}
location = /_internal_user_profile/ { internal; rewrite ^/(_internal_user_profile)/(\d+)$ /api/user.php?id=$2 break; alias /var/www/html/; }
location = /_internal_post_detail/ { internal; rewrite ^/(_internal_post_detail)/(\d+)$ /api/post.php?id=$2 break; alias /var/www/html/; }
这样就把鉴权逻辑和路由解耦,更易维护,也避免 rewrite 多次跳转带来的性能损耗。
四、验证与排错要点
部署后务必测试以下几项:
- ✅
curl -I https://example.com/user/profile/123→ 应返回 200 - ❌
curl -I https://example.com/api/user.php?id=123→ 应返回 404 或 403 - ❌
curl -I https://example.com/user.php→ 应返回 403(由deny all拦截) - ⚠️ 若出现 500 或 404,检查:
alias路径末尾是否多写了斜杠;internal是否写在了错误的 location;rewrite 的 flag 是否用了last而非break(影响 location 匹配)
这种模式不依赖 PHP 框架层控制,从 Web 服务器层面就切断非法路径,安全边界更清晰,适合高敏感接口场景。


















