Skip to content

偽靜態規則

程式只有 index.php 一個入口,所有頁面都靠它路由。不配偽靜態,除了首頁什麼都打不開。

Docker 安裝不需要配,映像裡已經寫好了。

下面三份規則語義完全一致:既做偽靜態轉發,也順手把不該被訪問的檔案擋在外面(日誌、資料庫備份、配置、.envcomposer.json 等)。建議整段複製,不要只抄最後那條 location /

Nginx

寶塔使用者:網站 → 點站點 → 偽靜態,整段粘進去儲存。

nginx
# 只放行唯一入口 index.php,其餘 .php 一律不執行
if ($uri ~* "^/(?!index\.php(/|$)).*\.php(/|$)")             { return 404; }

location ~* ^/(runtime|kernel|config|vendor)/                { return 404; }
location ~  /\.(?!well-known)                                { return 404; }
location ~* \.(log|sql|sqlite|db|db-wal|db-shm|bak|old|save|orig|swp|swo|tmp|ini|lock)$  { return 404; }
location ~* (~|composer\.(json|lock)|package(-lock)?\.json)$ { return 404; }
location / {
    try_files $uri $uri/ /index.php?s=$uri&$args;
}

第一條 if 為什麼不寫成 location:寶塔的配置模板裡,PHP 的 include enable-php-XX.conf 排在偽靜態之前,而 nginx 的正則 location按出現順序匹配、首個命中即止 —— 寫成 location ~ \.php$ 永遠輪不到它執行,會靜默失效。if 跑在更早的 rewrite 階段,不受順序影響。

Apache

不用配。 程式根目錄的 .htaccess 已經寫好了,確認它沒被上傳工具漏掉即可。

只要確認 Apache 開了 mod_rewrite,並且站點配置裡 AllowOverride 不是 None

IIS

Windows + IIS 需要裝 URL Rewrite 2.0 模組,然後把下面這段放進站點根目錄的 web.config(寶塔 Windows 版直接粘到偽靜態框裡):

xml
<rules>
	<!-- ① 程式目錄 -->
	<rule name="acg_deny_dir" stopProcessing="true">
		<match url="^(runtime|kernel|config|vendor)(/|$)"/>
		<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
	</rule>

	<!-- ② 點檔案 / 點目錄(放行 ACME 證書校驗) -->
	<rule name="acg_deny_dotfile" stopProcessing="true">
		<match url="(^|/)\.(?!well-known)"/>
		<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
	</rule>

	<!-- ③ 敏感字尾 -->
	<rule name="acg_deny_ext" stopProcessing="true">
		<match url="\.(log|sql|sqlite|db|db-wal|db-shm|bak|old|save|orig|swp|swo|tmp|ini|lock)$"/>
		<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
	</rule>

	<!-- ④ 備份副本與依賴清單 -->
	<rule name="acg_deny_file" stopProcessing="true">
		<match url="(~|composer\.(json|lock)|package(-lock)?\.json)$"/>
		<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
	</rule>

	<!-- ⑤ 只放行唯一入口 index.php -->
	<rule name="acg_deny_php" stopProcessing="true">
		<match url="^(?!index\.php(/|$)).*\.php(/|$)"/>
		<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
	</rule>

	<!-- ⑥ 偽靜態 -->
	<rule name="acg_rewrite" stopProcessing="true">
		<match url="^(.*)$"/>
		<conditions logicalGrouping="MatchAll">
			<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
			<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
		</conditions>
		<action type="Rewrite" url="index.php?s={R:1}" appendQueryString="true"/>
	</rule>
</rules>

用的是 URL Rewrite 1.x 的話不支援 CustomResponse,把它換成 <action type="AbortRequest"/>,代價是響應體為空。

不要改用 requestFilteringhiddenSegments 它是任意層級匹配的,會把 /admin/config/... 後臺配置頁和外掛自帶的 assets/vendor/assets/.../config/ 靜態資源一起 404 掉。

站點根目錄下放了別的 PHP 程式?

上面三份規則都只放行 index.php 一個入口。如果你在網站根目錄裡還放了 phpMyAdmin、adminer 之類的 PHP 工具,它們會被一起擋掉 —— 把這類工具挪到獨立站點即可。

驗證配好沒有

訪問下面幾個地址,都應該是 404

你的域名/composer.json
你的域名/runtime.log
你的域名/config/database.php

然後隨便點開一個商品頁面,能正常開啟就說明偽靜態生效了。

基於 MIT 協議開源