Назад | Перейти на главную страницу

htaccess измените корень документа на / public и запретите использование / public

Я размещаю приложение узла, и моя структура папок выглядит так:

mydomain.com
--index.js
--package.json
--public\test.txt

Я хочу лечить public в качестве корня моего документа и не разрешать доступ к чему-либо выше, например package.json.

Я сейчас использую .htaccess чтобы изменить "корень документа":

RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/$1 [L]

Это нормально работает, и я могу получить доступ http://example.com/test.txt, но это также означает, что http://example.com/public/test.txt тоже работает.

Как я могу предотвратить public от прямого использования в URL-адресе и использования только за кулисами?

Я пробовал добавить RewriteRule ^public/ - [L,R=404] до конца, но в итоге возвращаю 404 за все.

Чтобы уточнить, вы на самом деле не меняете корень документа здесь, вы фактически скрываете подкаталог с помощью перезаписи URL. Чтобы действительно изменить корень документа, вам нужно изменить DocumentRoot директива в конфигурации сервера (как упоминалось в комментариях), что будет иметь другие последствия (ваше приложение узла, вероятно, зависит от DocumentRoot устанавливается как есть).

RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/$1 [L]

Это проверяет отсутствие "public /" везде внутри запрошенного URL-пути, что на самом деле не то, что вам нужно. Однако RewriteCond директива здесь не нужна. Вместо этого вам следует проверять URL-путь в RewriteRule шаблон. Например:

 RewriteRule !^public/ /public%{REQUEST_URI} [L]

Обратите внимание, что REQUEST_URI Переменная сервера включает префикс косой черты. (Возможно, именно поэтому вы удалили якорь в своем CondPattern для того, чтобы заставить его "работать"?)

Я пробовал добавить RewriteRule ^public/ - [L,R=404] до конца, но в итоге возвращаю 404 за все.

Это правильная идея, но это тоже перенаправит переписанный URL-адреса (по другой директиве). Вам нужно только нацелить прямые запросы. Есть несколько способов сделать это. Я предпочитаю проверить REDIRECT_STATUS переменная окружения, которая пустой изначально и установлено на "200" после первой успешной перезаписи. Например:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]

($|/) - Обратите внимание, что я также сделал конечную косую черту «необязательной», так как она будет соответствовать либо public или public/ (с помощью чередование) при доступе к пустому каталогу. Это сделано для того, чтобы mod_dir сначала не выполнил перенаправление 301 для добавления завершающей косой черты в каталоге, прежде чем отправлять 404 в ответ на перенаправленный (второй) запрос. Чередование (конец строки или слэш) гарантирует, что public/<foo> совпадает, но нет public<foo>, если у вас есть URL-адреса, начинающиеся с "общедоступных" (например, /public-enemy).

Нет необходимости в L флаг при использовании кода состояния, отличного от 3xx (или 2xx), как есть подразумевается.

В итоге:

# Block direct requests to the "public" subdirectory
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]

# Rewrite all requests that are not already for the "public" subdirectory
RewriteRule !^public/ /public%{REQUEST_URI} [L]

Обратите внимание, что директива блокировки (404) должна быть первой.