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 协议开源