Eu tenho um pequeno aplicativo da web PHP / Apache2 no qual gostaria de fazer duas operações aparentemente incompatíveis:
- Encaminhar todas as solicitações por meio de um único script PHP (um "front controller", se desejar)
- Proteger tudo, exceto as chamadas de API com autenticação básica HTTP
Eu posso satisfazer qualquer requisito muito bem isoladamente, é quando tento fazer as duas coisas de uma vez que estou bloqueado. Por nenhuma boa razão eu estou tentando cumprir esses requisitos apenas com a configuração do Apache.
Aqui estão os requisitos indicados como exemplo. Um pedido de GET
para este URL:
http://basic/api/listcars?max=10
deve ser enviado por front.php
sem exigir autorização básica. front.php
obterá /api/listcars?max=10
e fará o que for necessário com isso.
Aqui está o que eu acho que deveria funcionar. No meu /etc/hosts
adicionei
127.0.0.1 basic
e estou usando esta configuração do 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>
Mas eu ainda sempre recebo uma resposta HTTP 401: Authorization Required
. Eu posso fazer funcionar alterando <Location /api>
para
<Location ~ /api>
mas isso permite mais do que eu quero para a autenticação básica do passado.
Eu também tentei alterar a seção <Directory /var/www/basic>
para <Location />
, mas isso também não funciona (e isso resulta em valores estranhos para PATH_TRANSLATED
sendo passado para o script).
Pesquisei e encontrei muitos exemplos de exclusão seletiva de autenticação básica, mas nenhuma que também incorporasse um front controller.
Eu certamente poderia fazer algo como lidar com a autenticação básica no front controller, mas se eu puder ter o Apache, em vez disso, poderei manter toda a lógica de autenticação fora do meu código PHP.
Um amigo sugeriu dividir isso em dois vhosts, que eu sei que também funciona. Isso costumava ser dois vhosts separados, na verdade.
<Location />
está fora do vhost porque quero que todos os vhosts exijam autenticação básica por padrão. A única exceção que desejo fazer é para todos os URIs começando com / api neste vhost em particular. Eu omiti outros vhosts porque eles não pareciam relevantes para minha pergunta.
Estou usando o Apache 2.2.22 / PHP 5.3.10 no Ubuntu 12.04.