Skip to content

URL 書き換えルール

このプログラムの入口は index.php ひとつだけで、すべてのページはそこを経由して振り分けられます。URL 書き換えを設定しないと、トップページ以外は何も開けません。

Docker でインストールした場合、この設定は不要です(イメージに組み込み済み)。

以下の 3 つのルールは意味的に同じものです。書き換えを行うと同時に、公開すべきでないファイル(ログ、データベースダンプ、設定、.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;
}

最初のルールが location ではなく if である理由:宝塔の設定テンプレートでは include enable-php-XX.conf が疑似静的の include よりに置かれており、nginx の正規表現 location記述順に評価されて最初に一致したところで止まります。そのためここに location ~ \.php$ と書いても永久に到達せず、何も起きないまま無効になります。if はより早い rewrite フェーズで動くので、順序の影響を受けません。

Apache

設定不要です。 プロジェクトルートの .htaccess が対応済みなので、アップロード時に漏れていないかだけ確認してください。

Apache 側で mod_rewrite が有効になっていること、サイトの AllowOverrideNone でないことを確認します。

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 を置いている場合

上記 3 つのルールはいずれも index.php 以外の実行を許可しません。phpMyAdmin や adminer などをサイトルートに置いている場合は一緒に遮断されるので、そうしたツールは別サイトへ移してください。

設定できたかの確認

次のアドレスにアクセスし、すべて 404 になれば正解です。

あなたのドメイン/composer.json
あなたのドメイン/runtime.log
あなたのドメイン/config/database.php

そのうえで任意の商品ページが正常に開けば、書き換えは効いています。

MIT ライセンスで公開