Não é possível excluir um caminho da autenticação básica ao usar um script do front controller

2

Eu tenho um pequeno aplicativo da web PHP / Apache2 no qual gostaria de fazer duas operações aparentemente incompatíveis:

  1. Encaminhar todas as solicitações por meio de um único script PHP (um "front controller", se desejar)
  2. 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.

    
por Adam Monsen 08.06.2012 / 08:40

1 resposta

1

Como o RewriteRule que está modificando o caminho está em um bloco <Directory> (o que foi feito para tornar %{SCRIPT_FILENAME} o caminho completo do arquivo), o sinal [PT] está implícito na regra. Como o [PT] sinalizador se aplica, o URL da nova solicitação é mapeado novamente em relação aos locais - e a seção <Location /api> não se aplica mais à solicitação.

Então, considerando isso, há algumas opções.

  • Tire suas regras de reescrita do bloco <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>
    
  • Use esse regex <Location> - ele pode ser restrito para evitar correspondências não intencionais.

    <Location ~ "(^|^/front\.php)/api/[^/]*$">
    
  • Use FallbackResource em vez de mod_rewrite .

    FallbackResource /front.php
    
por 09.06.2012 / 02:46

Tags