Исключение каталога из корневого правила перезаписи.htaccess, чтобы он был защищен паролем?

На прошлой неделе я потратил огромное количество времени, пытаясь выяснить это, но независимо от того, что я пытаюсь, я не могу заставить это работать. Мой веб-хостинг сказал, что у них не было никого, кто знал бы достаточно о файлах.htaccess, чтобы заставить его работать (обнадеживающе, верно?), И компания, у которой я купил мою CMS, также не смогла найти решение. Я также прочитал десятки на десятки ответов здесь и на других сайтах, но я просто не могу решить свою проблему.

Вот предложение: Моя CMS - Invision Power Board - генерирует следующий файл.htaccess, который находится в корне сайта:

<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} .*\.(jpeg|jpg|gif|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /public/404.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

У меня есть подкаталог, sub_dir, что мне нужно защитить паролем с помощью файла.htaccess в подкаталоге. Я устанавливаю защиту паролем через cPanel, и если файл.htaccess в корне сайта отключен, он работает нормально. Если файл.htaccess в корневом каталоге сайта не отключен, тогда, когда я просматриваю sub_dir домашняя страница отображается. Сначала я подумал, что отображаемая домашняя страница может иметь какое-то отношение к перезаписи страницы 404, но домашняя страница все равно отображается, даже если я удаляю условия перезаписи и правило для страницы 404.

Код в файле.htaccess в sub_dir является:

AuthUserFile "/home/[user]/public_html/.htpasswd"
AuthType Basic
AuthName "subdir"
require valid-user

Как я уже упоминал ранее, защита паролем работает, когда файл.htaccess в корневом каталоге отключен. Это также работает, когда я удаляю нижние условия и правила перезаписи (строки для index.php), но удаление условий и правил перезаписи для страницы 404 ни на что не влияет.

Я испробовал десятки потенциальных решений, ни одно из которых не сработало. Чтобы назвать несколько, я попробовал ответ Пончи ниже:

RewriteCond %{REQUEST_URI} !^sub_dir

Я также попробовал это:

RewriteRule ^/sub_dir  - [L]

Как и многие, многие другие вещи, которые я сейчас даже не помню. Дело в том, что пока ничего не получалось. Я также попробовал все возможные комбинации в отношении начальных и последующих слешей.

Мой сервер работает под управлением Apache 2.2.22.

Я серьезно в моем уме остроумие здесь. Пожалуйста помоги.

8 ответов

Решение

Казалось бы, вы уже пробовали это, это самый очевидный ответ (как указал Понча), и он, вероятно, наиболее вероятен в учебнике / руководстве по mod_rewrite. Исключая каталог, используя RewriteCond отмечая, что соответствие условия %{REQUEST_URI}, который начинается с / ":

<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/sub_dir
RewriteCond %{REQUEST_FILENAME} .*\.(jpeg|jpg|gif|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /public/404.php [L]

RewriteCond %{REQUEST_URI} !^/sub_dir
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

РЕДАКТИРОВАТЬ:

Глядя на то, что вы пробовали, это тоже неправильно. Вы не хотите, чтобы ведущий слеш в матче RewriteRule когда это находится в файле htaccess:

<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On

RewriteRule ^sub_dir  - [L]


RewriteBase /
RewriteCond %{REQUEST_FILENAME} .*\.(jpeg|jpg|gif|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /public/404.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Первое уведомление:

AuthUserFile "/home/[user]/public_html/.htpasswd"

Похоже, ваш файл.htpasswd находится в общедоступном месте (public_html). Это проблема безопасности, вы должны поместить этот файл куда-нибудь, где пользователь apache сможет его прочитать (проверьте права на каталог и права на файлы), но определенно не в месте под DocumentRoot. Никто не может напрямую запросить файл.htpasswd, это файл только на стороне сервера. Но это не связано с вашей проблемой.

Ваша главная проблема в том, что вы не ответили на вопросы @Jon Lin & @mootinator. Какие файлы вы пытаетесь запросить в sub_dir, есть ли там html-файлы, другой файл index.php? Вы должны разрешить листинг каталога в этом каталоге? Как вы делаете свои тесты.

Когда выполняется запрос к sub_dir, родительский.htaccess применяется по умолчанию (пытаясь перенаправить каждый запрос, который вы можете себе представить, в boostrapper index.php, за исключением файлов отсутствующих изображений и за исключением существующих каталогов или файлов). Поэтому, запрашивая настоящий файл в sub_dir, у вас не должно возникнуть проблем с этими правилами. Хороший способ проверить это - прокомментировать правила вашего root.htaccess.

Вы сказали, что сделали несколько тестов без корневого файла.htaccess, и это сработало. Так что, возможно, удаление Options -MultiViews что сделало ваши тесты в порядке. MultiViews - это часть отрицательного отношения к контенту, и это очень волшебное слово с очень странным поведением, поэтому, например, вы запрашиваете subd_dir/foo в ваших тестах MultiViews мог найти файл sub_dir/FoO.html и служить ему. Удалите MultiViews, и ваши тесты больше не будут работать (возможно). Предложения @Mootinator по проблемам символьных ссылок также могут быть действительными, и в тестируемых файлах также может быть что-то, перенаправляющее на URL, перехваченный по первому правилу, странным вещам нет конца. Но точно "это не работает" недостаточно, что такое "это"?

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

Это правило перенаправляет на домашнюю страницу, если запрошенный путь не является существующим файлом и не является существующим каталогом.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Очевидно, что поскольку вы перенаправлены на домашнюю страницу, сервер считает, что либо sub_dir каталог не существует, или запрос на sub_dir перенаправляется на то, что не существует.

Первое, что нужно проверить в этом сценарии, это, конечно, sub_dir является реальным каталогом, имея в виду, что в зависимости от вашего имени имя каталога будет чувствительным к регистру в большинстве случаев, когда работает Apache, а также помните, что символическая ссылка не обязательно обрабатывается так же, как каталог.

Вышеприведенные решения не работают, потому что они не решают фундаментальную проблему, заключающуюся в том, что подпапка, исключаемая из правил, защищена паролем.

Когда Apache отклоняет первоначальный доступ и открывает диалоговое окно входа в систему, правила перезаписи включаются, но не могут перенаправить клиента в доступный файл, поэтому возникает ошибка 404. Чтобы решить эту проблему, мы должны предоставить "фиктивный" файл, к которому клиент может быть направлен в случае неудачной попытки первоначального доступа.

ErrorDocument 401 /failed_auth.html
RewriteCond %{REQUEST_URI} ^/pwd-protected-sub-folder/(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^/failed_auth.html$
RewriteRule ^.*$ - [L]

Как насчет того, чтобы попытаться сделать это в своем sub_dir.htaccess, чтобы запретить modrewrite распространяться на ваш sub_dir:

    ## turn off rewrite engine
    RewriteEngine Off
    ## now do your auth stuff
    AuthUserFile "/home/[user]/public_html/.htpasswd"
    AuthType Basic
    AuthName "subdir"
    require valid-user

и если вам действительно нужно переписать правила для работы внутри sub_dir, то делайте их специально в этом файле.htaccess, чтобы не было путаницы. Как только вы выполняете RewriteEngine On/Off, правила из родительской папки не применяются напрямую. Сначала они читаются из этой папки, затем из корня.

Добавить еще RewriteCond исключить желаемое sub_dir (к обоим правилам):

RewriteCond %{REQUEST_URI} !^sub_dir

Добавляя это в надежде, что это поможет кому-то еще. @ Майк Л был на правильном пути с этим, я думаю. У меня была похожая ситуация (защищенный паролем подкаталог htaccess с правилами перезаписи в корневом htaccess, который мне все еще нужен для основного сайта). В итоге я решил просто добавить это в корневой файл.htaccess.

ErrorDocument 401 "Unauthorised"

Вам, конечно, все равно нужно будет добавить соответствующие правила, чтобы разрешить доступ к подкаталогу, но не отображаемый запрос пароля был исправлен с помощью описанного выше. Надеюсь, поможет!

Для сайта, использующего обычный виртуальный хостинг на основе cPanel (Apache 2.2), я решил ту же проблему, добавив файл с именем "401.shtml" в корневой каталог документа (public_html). Простое существование файла, даже без директивы ErrorDocument 401 в.htaccess, решило проблему.

Другие вопросы по тегам