Указать всем на index.php конфликт с частным каталогом
Вот структура моего сайта (корневая):
private
public
.htaccess
index.php
Файл htaccess содержит:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /index.php [L]
Сказав это, все URL-адреса указывают на index.php
В папке private
У меня также есть файл .htaccess
, который содержит:
Order Deny,Allow
Deny from all
Проблема в том, что http://www.example.com/private/
выбрасывает 403, а я этого не хочу. Возможно, я захочу использовать http://www.example.com/private/
местоположение, чтобы показать что-то на своем веб-сайте.
Я должен упомянуть, что я не хочу прикасаться к файлу .htaccess
из папки private
в любом путь.
Итак, я ищу способ установить некоторые правила в основном файле .htaccess
.
Как мне это сделать? Возможно ли это?
Редактировать: Подробнее о моей проблеме.
Представьте себе CMS с общей папкой и личной папкой. Папка private
даже не принадлежит корневому веб-серверу. Он не должен находиться в public_html, www или других общедоступных папках. Ну, говоря о CMS, не все пользователи понимают это, и они все еще могут хранить папку private
в public_html.
С учетом сказанного, папка private
должна содержать файл htaccess, который запрещает доступ к файлам через браузер (пример www.example.com/private/internal_script.php).
Но я все еще хочу иметь возможность отображать контент в браузере для www.example.com/private/
местоположения.
Прямо сейчас я могу размещать любой контент, какой захочу, по любому URL-адресу. Это связано с основным файлом htaccess, который позволяет мне выбирать, что показывать с помощью PHP. Но я все еще не могу отправлять контент по URL www.example.com/private/
, потому что это указывает на частный каталог, который содержит htaccess с запретом доступа.
www.example.com/hello/
может быть категория, статья и т. Д.
www.example.com/awesome/
может быть категория, статья и т. Д.
www.example.com/private/
не может быть ничего. Я получаю 403...
2 answers
Это технически возможно, однако существует другое "предпочтительное" решение для "CMS с папкой public
и папкой private
" (см. Ниже).
Чтобы кратко изложить требования:
- Разрешить маршрутизацию запросов для
/private/
или/private/<something>
(где<something>
не является физическим файлом в подкаталоге/private
) через фронт-контроллер (т.е./index.php
в корневом каталоге). Как и любой другой (не файловый) URL-адрес. - Любые HTTP-запросы для
/private/<actual-file>
должны быть заблокированы (403 Запрещено), в том виде, в каком они есть в настоящее время. (ОБНОВЛЕНИЕ: Хотя это не требуется, кажется, что это должно быть переписано на фронт-контроллер, как в #1) - Можно изменить только родительский файл
.htaccess
в корневом каталоге документа.
Нам в основном нужно "переопределить" ответ 403 Forbidden для защищенного подкаталога, когда запрашивается либо сам каталог, либо не файл в этом подкаталоге.
Обычно директивы в подкаталоге .htaccess
директивы переопределения файла в родительском файле .htaccess
, поэтому нам нужно изменить порядок обработки и убедиться, что необходимые "переопределяющие" директивы в родительском файле .htaccess
обрабатываются позже . Это может быть достигнуто путем упаковки директив в контейнер <Files>
(или <FilesMatch>
) или в блок <If>
с использованием выражения Apache .
Однако дополнительным осложнением в данном конкретном случае является использование устаревшего (Apache 2.2 и более ранних версий) Order
и Deny
директивы в защищенном подкаталоге. (В Apache 2.4, который, как я полагаю, вы используете, вместо этого вы должны использовать директиву single Require all denied
.) Чтобы "переопределить" директивы авторизации в подкаталоге, вы должны использовать тот же метод авторизации. (Именно поэтому в документах Apache подчеркивается, что вам следует избегать смешивания двух (старых и новых) методов авторизации. Старые/устаревшие директивы предоставляются только для обратной совместимости и должны быть перенесены - полностью - при первой же возможности. Будучи официально устаревшими, они будут полностью удалены в будущих версиях Apache.)
Итак, вы можете сделать что-то вроде следующего в корневом файле .htaccess
. Порядок директив строго не имеет значения, вы можете разместить его до или после вашего фронт-контроллера mod_rewrite, однако было бы логичнее иметь его до.
# For any request that starts "/private" and does not map to a physical file then...
<If "%{REQUEST_URI} =~ m#^/private# && !-f %{REQUEST_FILENAME}">
DirectoryIndex disabled
DirectorySlash Off
# If using Apache 2.4 directives...
#Require all granted
# If using old Apache 2.2 directives in the subdirectory then need to use the same here...
Order Deny,Allow
Allow from all
</If>
Необходимо отключить DirectoryIndex
для подкаталога, чтобы предотвратить попытку mod_dir обслуживать индексный документ (например, index.php
) при запросе чистого каталога. Если DirectoryIndex
включен, то... если индексный документ существует, то mod_dir выдает внутренний подзапрос, который затем блокируется, и URL-путь недоступен для вашей CMS. Если индексный документ не существует, то mod_dir блокирует запрос, и URL-путь недоступен для вашей CMS.
DirectorySlash Off
требуется только в том случае, если вы хотите иметь доступ к /private
без задней косой черты. Обычно mod_dir добавляет завершающую косую черту с перенаправлением 301, так как /private
является физическим каталогом.
ОБНОВЛЕНИЕ: С тех пор я понял, что вам не нужен #2 выше, и вы хотите просто переписать /private/<anything>
на /index.php
(ваш фронт-контроллер), даже если в противном случае он был бы сопоставлен с реальным файлом. В этом случае ваше измененное предложение выглядит хорошо:
<If "%{REQUEST_URI} =~ m#^/private#"> Order Deny,Allow Allow from all RewriteRule ^ /index.php [L] </If>
Он повторяет перезапись на фронт-контроллер (который все еще присутствует позже в файле .htaccess
), но это необходимо для переопределения DirectoryIndex
и для принудительной перезаписи любых запросов на физические файлы в подкаталоге /private
на фронт-контроллер (чтобы быть недоступным).
Я не уверен, что делает
=~ m#^/private#
, но я полагаю, что он проверяет, начинается ли URL-адрес с "/private". Мне также интересно, каков эффект, если URL-адрес начинается с/privatesomething
Да, он проверяет, что запрошенный URL-путь начинается /private
. =~
является регулярным выражением оператор сравнения и m#<regex>#
- это альтернативный синтаксис для регулярного выражения. Вы также можете использовать /<regex>/
(обычные разделители косой черты), но это, естественно, создает проблемы при проверке URL-адресов.
Вы не можете только проверить, что URL-адрес начинается /private/
(с завершающей косой черты), так как запрос на /private
(без завершающей косой черты) вызовет ответ 403 до того, как mod_dir добавит косую черту.
/privatesomething
также попадется на это, но это не должно иметь значения, так как вы только позволяете получите доступ и перепишите запрос - это то, что вы все равно хотите сделать.
Однако, если у вас есть физические файлы в корневом каталоге, которые не должны передаваться в CMS и обслуживаться напрямую, например/privatesomething.jpg
, то это действительно будет проблемой с вышеуказанным регулярным выражением. Это можно решить, изменив регулярное выражение так, чтобы оно соответствовало либо /private
или /private/something
, но не /privatesomething
. Например:
<If "%{REQUEST_URI} =~ m#^/private($|/)#">
CMS с папкой public
и папкой private
Как правило, при отправке CMS с помощью /public
и /private
подкаталог на том же уровне, то намерение, если у вас есть доступ к конфигурации сервера, состоит в том, чтобы изменить DocumentRoot
сервера, чтобы указать на подкаталог /public
. ИЛИ, если у вас нет доступа к конфигурации сервера, то безоговорочно перепишите запрос с помощью mod_rewrite в подкаталог /public
. И иметь дополнительный файл .htaccess
в подкаталоге /public
, содержащий ваш шаблон фронт-контроллера. (Все необходимые файлы должны быть поставляется с CMS - ничего не нужно редактировать вручную, кроме, возможно, комментария, если у вас есть доступ к конфигурации сервера.)
Этот метод скрывает путь к файлу /public
от видимого URL-адреса (что является намерением) и, естественно, решает проблему, обсуждавшуюся выше, с конфликтом URL-адреса с защищенным подкаталогом /private
.
Например, (если не изменять DocumentRoot
в конфигурации сервера), то в корневом файле .htaccess
:
RewriteEngine On
# Unconditionally rewrite all requests to the "/public" subdirectory
RewriteRule ^ /public%{REQUEST_URI} [L]
Тогда в /public/.htaccess
у вас есть ваш фронт-контроллер:
RewriteEngine On
# CMS front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Обратите внимание на отсутствие косой черты в начале RewriteRule
подстановка строка. Здесь должно быть index.php
, а не /index.php
.
Я немного поиграл с этим, и я не верю, что это возможно - по крайней мере, не в главном файле .htaccess, не нарушая ограничений сервера.
Я полагаю, что можно переопределить поведение по умолчанию, изменив файл конфигурации apache.
Возможно, имеет смысл переместить вашу личную конфигурацию выше корневого каталога документа (я предполагаю, что вы используете ее для включения контента с помощью чтения с PHP или аналогичного, или просто не имеете доступа к веб-серверу) - в этом случае вы можете создать еще один частный подкаталог в вашем корневом каталоге документов, который доступен через веб-сервер.