
本文详解如何利用 apache 的 .htaccess 文件将所有请求无损转发至单一 php 路由入口(如 router.php),避免 url 参数拼接导致的安全隐患,并推荐使用 $_server['request_uri'] 安全获取原始路径。
本文详解如何利用 apache 的 .htaccess 文件将所有请求无损转发至单一 php 路由入口(如 router.php),避免 url 参数拼接导致的安全隐患,并推荐使用 $_server['request_uri'] 安全获取原始路径。
在构建现代 PHP 路由系统(如类 Laravel 或自研轻量框架)时,常需将所有 HTTP 请求统一交由一个中心化路由文件(如 router.php)处理。常见误区是试图在 .htaccess 中显式重写为带查询参数的形式,例如:
# ❌ 错误示例:手动拼接 url= 参数(存在安全与语义问题) RewriteRule ^(.*)$ router.php?url=$1 [QSA,L]
这种写法不仅会破坏原始查询字符串结构(如 /register?redirect=page/category/stuff 中的 redirect 参数会被覆盖或混淆),更可能引发 URL 编码混乱、双重解码漏洞,甚至为恶意构造的 url= 参数埋下注入隐患。
✅ 正确做法是:不修改原始请求上下文,仅重写请求路径,让 PHP 自然保留完整请求信息。
✅ 推荐 .htaccess 配置(安全、简洁、标准)
# 启用重写引擎
RewriteEngine On
# 排除真实存在的静态资源(提升性能与兼容性)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 将所有非文件/非目录请求重写至 router.php(不改变 QUERY_STRING)
RewriteRule ^(.*)$ router.php [L]该配置的关键在于:
立即学习“前端免费学习笔记(深入)”;
- !-f 和 !-d 确保 css/style.css、images/logo.png 等真实资源直接由 Web 服务器响应,不经过 PHP;
- [L] 标志终止后续规则匹配;
- 未使用 [QSA](Query String Append)也无需手动拼接 ?url=... —— 原始查询字符串(如 ?redirect=page/category/stuff)会自动透传至 router.php。
✅ 在 router.php 中安全获取路由路径
无需解析 $_GET['url'],直接使用:
<?php
// router.php
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// → 对于 https://domain.smt/register?redirect=page/category/stuff
// $requestUri === '/register'
// 原始完整查询字符串仍可通过 $_GET 或 $_SERVER['QUERY_STRING'] 获取
$redirect = $_GET['redirect'] ?? null; // 安全获取,已由 PHP 自动解码
// 示例:简单路由分发
switch ($requestUri) {
case '/register':
include 'controllers/RegisterController.php';
break;
case '/login':
include 'controllers/LoginController.php';
break;
default:
http_response_code(404);
echo "Route not found";
}? 提示:首次调试时,可在 router.php 开头添加 快速验证实际接收的请求数据,直观确认路径与参数分离的完整性。
⚠️ 注意事项与最佳实践
- 永远不要信任用户输入路径:即使使用 $_SERVER['REQUEST_URI'],其值仍来自客户端。若需进一步解析(如提取 ID),务必配合白名单校验、正则匹配或类型转换(如 (int) 强转 ID);
- 确保 router.php 位于 Web 根目录,且 .htaccess 与其同级;
- 若部署在子目录(如 https://domain.smt/app/),需添加 RewriteBase /app/;
- 生产环境建议禁用 AllowOverride All 的过度权限,改用
块在主配置中启用重写,兼顾安全与性能。
通过此方案,你既实现了“所有路由交由单点处理”的架构目标,又规避了手动参数拼接引入的安全与维护风险——这不是过度设计,而是 Web 路由工程的通用范式。



















