Не удается исключить путь из базовой аутентификации при использовании сценария фронт-контроллера

У меня есть небольшое веб-приложение на PHP/Apache2, в котором я хотел бы выполнить две, казалось бы, несовместимые операции:

  1. Направляйте все запросы через один PHP-скрипт ("фронт-контроллер", если хотите)
  2. Защитите все, кроме вызовов 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
    
Другие вопросы по тегам