Не удается исключить путь из базовой аутентификации при использовании сценария фронт-контроллера
У меня есть небольшое веб-приложение на PHP/Apache2, в котором я хотел бы выполнить две, казалось бы, несовместимые операции:
- Направляйте все запросы через один PHP-скрипт ("фронт-контроллер", если хотите)
- Защитите все, кроме вызовов API, с помощью базовой аутентификации HTTP
Я могу удовлетворять любое требование в отдельности, но когда я пытаюсь сделать оба сразу, я блокируюсь. Без всякой веской причины я пытаюсь выполнить эти требования исключительно с помощью конфигурации Apache.
Вот требования, изложенные в качестве примера. GET
запросить этот URL:
http://basic/api/listcars?max=10
следует отправить через front.php
без необходимости базовой аутентификации. front.php
получите /api/listcars?max=10
и делай с этим все, что нужно.
Вот то, что я думаю, должно работать. В моем /etc/hosts
я добавил
127.0.0.1 basic
и я использую эту конфигурацию Apache:
<Location />
AuthType Basic
AuthName "Home Secure"
AuthUserFile /etc/apache2/passwords
require valid-user
</Location>
<VirtualHost *:80>
ServerName basic
DocumentRoot /var/www/basic
<Directory /var/www/basic>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ /front.php/$1 [QSA,L]
</IfModule>
</Directory>
<Location /api>
Order deny,allow
Allow from all
Satisfy any
</Location>
</VirtualHost>
# another extant vhost in the same Apache2 config/server, for completeness
<VirtualHost *:80>
ServerName dustbin
ServerAlias *.dustbin
DocumentRoot /var/www/dustbin
</VirtualHost>
Но я все еще всегда получаю HTTP 401: Authorization Required
ответ. Я могу заставить его работать, изменив <Location /api>
в
<Location ~ /api>
но это позволяет больше, чем я хочу, чтобы пройти базовую аутентификацию.
Я также пытался изменить <Directory /var/www/basic>
раздел в <Location />
, но это тоже не работает (и это приводит к некоторым странным значениям для PATH_TRANSLATED
передается в сценарий).
Я искал вокруг и нашел много примеров выборочного исключения базовой аутентификации, но ни один, который также включал фронт-контроллер.
Я, конечно, мог бы сделать что-то вроде обработки базовой аутентификации во фронт-контроллере, но если я смогу сделать так, чтобы Apache сделал это, я смогу сохранить всю логику аутентификации вне своего кода PHP.
Друг предложил разделить это на два vhosts, которые я знаю, также работает. Вообще-то, раньше это были два отдельных призрака.
<Location />
находится за пределами vhost, потому что я хочу, чтобы все vhosts по умолчанию требовали базовую аутентификацию. Единственное исключение, которое я хочу сделать, касается всех URI, начинающихся с /api на этом конкретном vhost. Я пропустил других vhosts, потому что они не относились к моему вопросу.
Я использую Apache 2.2.22 / PHP 5.3.10 в Ubuntu 12.04.
1 ответ
Поскольку RewriteRule
это изменение пути в <Directory>
блок (который был сделан для того, чтобы сделать %{SCRIPT_FILENAME}
полный путь к файлу), [PT]
флаг подразумевается в правиле. Поскольку [PT]
флажок применяется, URL нового запроса повторно сопоставляется с местоположениями - и <Location /api>
раздел больше не относится к запросу.
Итак, учитывая это, есть несколько вариантов.
Возьмите свои правила переписывания из
<Directory>
блок.<VirtualHost *:80> ServerName basic DocumentRoot /var/www/basic RewriteEngine On RewriteCond /var/www/basic%{REQUEST_URI} !-f RewriteCond /var/www/basic%{REQUEST_URI} !-d RewriteRule ^(.*)$ /front.php/$1 [QSA,L] <Location /api> Order deny,allow Allow from all Satisfy any </Location> </VirtualHost>
Используйте это регулярное выражение
<Location>
- это может быть ограничено, чтобы предотвратить непреднамеренные совпадения.<Location ~ "(^|^/front\.php)/api/[^/]*$">
использование
FallbackResource
вместоmod_rewrite
,FallbackResource /front.php