偽靜態將動態 URL (index.php?id=1) 重寫為靜態風格 (/article/1.html),利於 SEO、美觀、隱藏技術細節。本文詳解五種實現方案:Apache mod_rewrite、Nginx rewrite、PHP PATH_INFO 解析、自定義路由類、框架級路由,並說明 SQL 注入繞過風險與防護。
# httpd.conf
LoadModule rewrite_module modules/mod_rewrite.so
AllowOverride All # 允許 .htaccess
RewriteEngine On
# 將 /article/123.html 重寫為 index.php?action=article&id=123
RewriteRule ^([a-zA-Z]+)-([0-9]+)\.html$ index.php?action=$1&id=$2 [L,QSA]
# 通用:所有非實體檔案導向 index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
# nginx.conf
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# 或特定規則
location / {
rewrite ^/([a-z]+)-([0-]+)\.html$ /index.php?action=$1&id=$2 last;
}
URL 格式:https://domain.com/index.php/article/123
<?php
// 入口檔 index.php
$pathInfo = $_SERVER['PATH_INFO'] ?? '/'; // /article/123
$pathInfo = trim($pathInfo, '/');
$segments = explode('/', $pathInfo);
$action = $segments[0] ?? 'index';
$id = $segments[1] ?? 0;
// 派發
include "controllers/{$action}.php";
注意: 部分需在 php.ini 設定 cgi.fix_pathinfo=1,Nginx 需 fastcgi_param PATH_INFO $fastcgi_path_info;。
<?php
class Router {
private $routes = [];
public function get($pattern, $handler) {
$this->routes['GET'][$pattern] = $handler;
}
public function dispatch() {
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
foreach ($this->routes[$method] ?? [] as $pattern => $handler) {
// 簡易正則轉換:/article/{id:\d+} → 正則
$regex = preg_replace('/\{(\w+)(?::([^}]+))?\}/', '(?P<$1>$2)', $pattern);
$regex = '@^' . $regex . '$@';
if (preg_match($regex, $uri, $matches)) {
// 過濾數字索引,保留命名捕獲
$params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
return call_user_func_array($handler, $params);
}
}
http_response_code(404);
echo 'Not Found';
}
}
// 使用
$router = new Router();
$router->get('/article/{id:\d+}', function($id) {
echo "Article ID: $id";
});
$router->dispatch();
// Laravel 風格 routes/web.php
Route::get('/article/{id}', 'ArticleController@show');
Route::post('/article', 'ArticleController@store');
// 對應控制器
class ArticleController {
public function show($id) {
return Article::findOrFail($id);
}
}
原文提到利用偽靜態中轉頁面繞過 WAF 注入檢測:
<?php
// inj.php - 危險範例(僅供理解原理,嚴禁生產使用)
$id = $_GET['id'];
$url = "https://target.com/index.php/library/more/id/$id.html";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($ch);
防護:
curl/file_get_contents 異常外連id 必須純數字)| 場景 | 推薦方案 | 理由 |
|---|---|---|
| Apache 虛擬主機、共享主機 | .htaccess mod_rewrite | 無需 root 權限、相容性佳 |
| Nginx + PHP-FPM 生產環境 | Nginx rewrite + try_files | 效能最佳、配置集中 |
| 快速原型、無法修改 Web Server | PATH_INFO | 零配置、PHP 內部解析 |
| 中大型專案、長期維護 | 框架級路由 | 結構化、中介軟體、測試友善 |
偽靜態本質是 URL 重寫 + 參數解析 + 路由派發。現代專案建議直接使用成熟框架路由系統,手動實作僅適合學習或極輕量專案。無論何種方案,**輸入驗證與參數化查詢** 才是資安根本。