Apache: serve conteúdo de arquivos restritos

1

Na minha configuração do Apache, tenho um diretório com minhas páginas de erro (404 403). No entanto, eu não quero que esse diretório seja visível diretamente - eu gostaria de acessá-lo para retornar um 404. Então, o que eu fiz foi isso:

# Use /hidden/404/ as the 404 page
ErrorDocument 404 /hidden/404/
# Use /hidden/403/ as the 403 page
ErrorDocument 403 /hidden/403/
<Directory /path/to/root/hidden/>
    # All requests return 404
    RedirectMatch 404 .*
</Directory>

o problema é que o Apache parece não estar disposto a servir os arquivos em todos neste caso, mesmo quando eu digo explicitamente (isto é, para lidar com erros 404 e 403). Na verdade, quando visito /hidden , recebo a seguinte mensagem:

The requested URL /hidden/404/ was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an 
ErrorDocument to handle the request.

De qualquer forma, posso dizer ao Apache para não permitir o acesso ao diretório enquanto ainda permite servir a esses arquivos quando necessário?

    
por joshlf 07.08.2014 / 15:39

1 resposta

0

OK, descobri uma maneira de fazer isso.

O que fiz foi usar mod_rewrite , que é um módulo do Apache (enviado por padrão com todas as instalações) para reescrever os URLs solicitados na hora. Aqui está o código:

# Custom error pages
ErrorDocument 404 /hidden/404/index.html
ErrorDocument 403 /hidden/403/index.html

# Pretend that /hidden doesn't exist
# (unless this is an internal redirect,
# such as rendering a 404 or 403)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^/hidden/.* - [L,R=404]

Então, vamos percorrer essas linhas. As diretivas ErrorDocument não foram alteradas - elas apenas dizem qual página deve ser exibida quando um determinado erro ocorre.

A carne real está nas diretivas RewriteCond e RewriteRule . O que a diretiva RewriteRule diz é a seguinte: se uma URL for solicitada cujo caminho coincida com o regex ^/hidden/.* (essencialmente, qualquer caminho que esteja em / hidden ou sua subárvore), deixe a URL inalterada (é isso que o - significa), mas não interpreta mais RewriteRule diretivas (é o que significa L ) e retorna um código de erro 404 (é o que significa R=404 ).

Isso, combinado com a diretiva ErrorDocument 404 /hidden/404/index.html , parece funcionar. O problema, no entanto, é que quando o Apache vai servir /hidden/404/index.html , ele executa essas regras novamente. Isso significa que a diretiva RewriteRule é executada, o que, por sua vez, diz para renderizar o 404, e a coisa toda apenas loops infinitos.

Assim, usamos a diretiva RewriteCond para garantir que isso não aconteça. As diretivas RewriteCond são condicionais - a diretiva RewriteRule abaixo só será executada se a condição for satisfeita. A condição, neste caso, é "a variável de ambiente REDIRECT_STATUS é igual à cadeia vazia". Agora, REDIRECT_STATUS é uma variável de ambiente definida por ErrorDocument e contém o código de status que está sendo redirecionado (portanto, se a diretiva ErrorDocument 404 ... tiver sido acionada, ela será configurada para o valor "404") . No entanto, se nenhuma diretiva ErrorDocument tivesse sido executada, então REDIRECT_STATUS não teria sido definido e, portanto, pedir seu valor simplesmente retornaria a string vazia. Assim, RewriteCond %{ENV:REDIRECT_STATUS} ="" essencialmente diz: "não se incomode em avaliar a diretiva RewriteRule abaixo, a menos que não estejamos no meio de uma página de erro".

note: Se você consultou a documentação de RewriteRule , você deve ter notado que o argumento R deveria executar um redirecionamento explícito. O motivo pelo qual funciona bem, nesse caso, é que há um recurso não documentado do argumento R , que apenas redireciona os códigos de 300 classes. Assim, R=404 não faz um redirecionamento explícito, apenas um interno.

    
por 07.08.2014 / 19:18