Apache 2.4: AuthType Basic и REQUEST_URI - сравнения (с регулярным выражением или без него) не работают должным образом

Мы используем Apache 2.4.10 на сервере Debian. Запросы перенаправляются с прокси-сервера Apache (той же системы и версии), который выступает в качестве балансировщика (только один участник баланса на данный момент).

Доступ к связанному одиночному виртуальному хосту обычно ограничен через AuthType Basic. Только одна папка, содержащая публичные документы, должна быть доступна без аутентификации.

Для этого я протестировал несколько способов (новый синтаксис apache 2.4), но независимо от того, какой метод я использовал, я всегда придерживался одной и той же проблемы: любое сравнение с REQUEST_URI не работает должным образом - с регулярным выражением или без него. Кажется, что REQUEST_URI имел недопустимое значение во время сравнения.

Я попробовал следующие варианты:

A)

<VirtualHost *:80>

ServerName domain.name
DocumentRoot /var/www/domain.name
DirectoryIndex index.php

<Directory "/var/www/domain.name/">

    AuthType Basic
    AuthName "Restricted"
    AuthBasicProvider file
    AuthUserFile /path/to/user/file

    <RequireAny>
        Require method OPTIONS
        Require expr %{REQUEST_URI} =~ m#^/docs#
        Require valid-user
    </RequireAny>

    Options +ExecCGI +FollowSymLinks
    AllowOverride All

</Directory>

CustomLog "/var/log/apache2/test_log" "%t REQUEST_URI:%{REQUEST_URI}e"

</VirtualHost>

B)

<VirtualHost *:80>

ServerName domain.name
DocumentRoot /var/www/domain.name
DirectoryIndex index.php

<Directory "/var/www/domain.name/">

    AuthType Basic
    AuthName "Restricted"
    AuthBasicProvider file
    AuthUserFile /path/to/user/file

    <RequireAny>
        Require method OPTIONS
        Require valid-user
    </RequireAny>

    Options +ExecCGI +FollowSymLinks
    AllowOverride All

</Directory>

<LocationMatch "^/docs">
    AuthType None
    Require all granted
</LocationMatch>

CustomLog "/var/log/apache2/test_log" "%t REQUEST_URI:%{REQUEST_URI}e"

</VirtualHost>

C)

<VirtualHost *:80>

ServerName domain.name
DocumentRoot /var/www/domain.name
DirectoryIndex index.php

<Directory "/var/www/domain.name/">

    SetEnvIf Request_URI /docs noAuth=1

    AuthType Basic
    AuthName "Restricted Files"
    AuthBasicProvider file
    AuthUserFile /path/to/user/file

    <RequireAny>
        Require method OPTIONS
        Require env noauth
        Require valid-user
    </RequireAny>

    Options +ExecCGI +FollowSymLinks
    AllowOverride All

</Directory>

CustomLog "/var/log/apache2/test_log" "%t REQUEST_URI:%{REQUEST_URI}e"

</VirtualHost>

Кажется, что каждая альтернатива застревает в той же самой проблеме. Сравнение с REQUEST_URI не выполняется или не работает должным образом.

Пример: когда я меняю строку 16 в примере А на

Require expr %{REQUEST_URI} =~ m#^/[a-z]#

(как тест), затем он работает (доступ предоставляется без учетных данных).

Когда я изменюсь [a-z] например [d-i], это все еще работает, но когда я изменяюсь [a-z] например [d-g], это больше не работает, и появляется диалог пользователя / прохода.

Точно такое же поведение появляется, когда я изменяю регулярное выражение в директиве LocationMatch в примере B соответственно.

Еще один намек:

С помощью <Location /docs> вместо <LocationMatch... (см. пример B) также не работает. Но <Location /> работает.

А также:

Лог-выход всегда идентичен:

Когда доступ предоставляется без учетных данных, значение REQUEST_URI совпадает с частью пути запрошенного URL (например, / docs).

Но когда появляется user / pass-dialog, значением является тире ("-"), это значение по умолчанию, которое apache использует для пустых или недоступных значений.

А также:

Проблема сохраняется, даже когда я обращаюсь к серверу напрямую (без прокси) или когда я использую, например, wget, чтобы сделать запрос к localhost на сервере.

У кого-нибудь есть идея, что здесь происходит?

2 ответа

Я наконец нашел обходной путь самостоятельно. Я использую версию A) - но с переменной окружения THE_REQUEST вместо REQUEST_URI, К счастью, это работает!

Скорректированная версия A) - только для запросов GET:

<VirtualHost *:80>

ServerName domain.name
DocumentRoot /var/www/domain.name
DirectoryIndex index.php

<Directory "/var/www/domain.name/">

AuthType Basic
AuthName "Restricted"
AuthBasicProvider file
AuthUserFile /path/to/user/file

<RequireAny>
    Require method OPTIONS
    Require expr %{THE_REQUEST} =~ m#GET\s+\/docs\/[^\/]+\s+HTTP#
    Require valid-user
</RequireAny>

Options +ExecCGI +FollowSymLinks
AllowOverride All

</Directory>

</VirtualHost>

Вместо использования Location вы можете использовать другой каталог.

<VirtualHost *:80>
    ServerName domain.name
    DocumentRoot /var/www/domain.name
    DirectoryIndex index.php
    <Directory "/var/www/domain.name/">
        AuthType Basic
        AuthName "Restricted"
        AuthBasicProvider file
        AuthUserFile /path/to/user/file
        <RequireAny>
            Require method OPTIONS
            Require valid-user
        </RequireAny>
        Options +ExecCGI +FollowSymLinks
        AllowOverride All
    </Directory>
    **<Directory "/var/www/domain.name/docs/">
        AuthType None
        Require all granted
    </Directory>**
    CustomLog "/var/log/apache2/test_log" "%t REQUEST_URI:%{REQUEST_URI}e"
</VirtualHost>

То же самое можно сделать с помощью.htaccess. Ответ на соответствующий вопрос дан в разделе Как удалить защиту паролем.htaccess из подкаталога.

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