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

Apache: обслуживать контент из файлов с ограниченным доступом

В моей настройке Apache у меня есть каталог со страницами с моими ошибками (404 403). Однако я не хочу, чтобы этот каталог был доступен для просмотра напрямую - я хотел бы получить к нему доступ, чтобы вернуть 404. Итак, я сделал следующее:

# Use /hidden/404/ as the 404 page
ErrorDocument 404 /hidden/404/
# Use /hidden/403/ as the 403 page
ErrorDocument 403 /hidden/403/
<Directory /path/to/root/hidden/>
    # All requests return 404
    RedirectMatch 404 .*
</Directory>

проблема в том, что Apache, похоже, не желает обслуживать файлы в все в этом случае, даже когда я говорю это явно (то есть для обработки ошибок 404 и 403). На самом деле, когда я навещаю /hidden, Я получаю следующее сообщение:

The requested URL /hidden/404/ was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an 
ErrorDocument to handle the request.

В любом случае я могу сказать Apache, чтобы он запретил доступ к каталогу, но при этом позволял себе обслуживать эти файлы при необходимости?

Хорошо, я нашел способ сделать это.

Я использовал mod_rewrite, который представляет собой модуль Apache (по умолчанию поставляется со всеми установками) для перезаписи запрошенных URL-адресов на лету. Вот код:

# Custom error pages
ErrorDocument 404 /hidden/404/index.html
ErrorDocument 403 /hidden/403/index.html

# Pretend that /hidden doesn't exist
# (unless this is an internal redirect,
# such as rendering a 404 or 403)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^/hidden/.* - [L,R=404]

Итак, давайте пройдемся по этим строкам. В ErrorDocument директивы не изменились - они просто говорят, какую страницу следует обслуживать при возникновении данной ошибки.

Настоящее мясо в RewriteCond и RewriteRule директивы. Что за RewriteRule директива говорит следующее: если запрашивается URL-адрес, путь которого соответствует регулярному выражению ^/hidden/.* (по сути, любой путь к чему-либо в / hidden / или его поддереве), оставьте URL-адрес без изменений (это то, что - означает), но больше не интерпретируйте RewriteRule директивы (вот что L означает), и вернуть код ошибки 404 (это то, что R=404 средства).

Это в сочетании с ErrorDocument 404 /hidden/404/index.html директива, может показаться, помогает. Проблема, однако, в том, что когда Apache переходит на обслуживание /hidden/404/index.html, он снова проходит через эти правила. Это означает, что RewriteRule выполняется директива, которая, в свою очередь, требует отрисовки 404, и все это просто бесконечные циклы.

Таким образом, мы используем RewriteCond директива, чтобы этого не произошло. RewriteCond директивы являются условными - RewriteRule указанная ниже директива будет выполнена только в том случае, если выполнено условие. В этом случае условием является "переменная среды REDIRECT_STATUS равно пустой строке. "Теперь REDIRECT_STATUS это переменная среды, которая устанавливается ErrorDocument, и содержит код состояния, который перенаправляется (так, если ErrorDocument 404 ... директива была запущена, ей будет присвоено значение "404"). Однако если нет ErrorDocument директива была выполнена, то REDIRECT_STATUS не было бы установлено, поэтому запрос его значения просто вернет пустую строку. Таким образом, RewriteCond %{ENV:REDIRECT_STATUS} ="" по сути говорит: "не беспокойтесь об оценке RewriteRule приведенной ниже директиве, если только мы не обрабатываем страницу с ошибкой ".


нота: если вы посмотрели на RewriteRule документации, вы могли заметить, что R Аргумент должен выполнять явное перенаправление. Причина, по которой он отлично работает в этом случае, заключается в том, что есть недокументированная функция R аргумент, который заключается в том, что он перенаправляет только коды класса 300. Таким образом, R=404 не делает явного перенаправления, только внутреннее.