Como posso proteger arquivos no meu servidor NGiNX?

1

Estou tentando proteger arquivos no meu servidor (vários tipos), com NGiNX e PHP.

Basicamente, quero que as pessoas tenham que entrar no site se quiserem acessar esses arquivos estáticos, como imagens. O DropBox faz isso muito bem. Onde por eles forçá-lo a entrar para acessar todos os arquivos estáticos que você colocar lá servidor.

Eu pensei em usar o NGiNX Perl Module. E eu escreveria um script perl que verificaria a sessão para ver se o usuário estava conectado para dar acesso a um arquivo estático.

Eu preferiria usar PHP porque todo o meu código está rodando em PHP e eu não tenho certeza de como verificar uma sessão criada pelo PHP com PERL.

Então, basicamente, minha pergunta é: como proteger arquivos estáticos de qualquer tipo que precisem do usuário para fazer login e ter uma sessão válida criada com um script PHP?

    
por jnbdz 19.11.2011 / 04:19

1 resposta

9

Há duas coisas que você está perguntando:

  1. Como impedir o acesso externo a um (conjunto de) arquivo (s)
  2. Como autenticar um usuário e permitir o acesso do PHP (e do usuário) ao (s) arquivo (s)

Espero que isso esclareça o papel que cada componente desempenha - embora possa ser um pouco excessivo.

Impedir acesso externo a arquivos:

Esta parte é feita pelo seu servidor web - neste caso nginx.

Em sua configuração nginx (seu bloco de servidor), você especifica um caminho root . Por padrão, todos os arquivos sob esse caminho raiz estão diretamente acessíveis.

Por exemplo, considere o seguinte (o domínio é 'exemplo.com')

root /var/www/example.com/public_html

Se você tiver um arquivo, uploaded_file.zip , ele estará acessível das seguintes maneiras:

  • Localização: /var/www/example.com/public_html/uploaded_file.zip - acessível via example.com/uploaded_file.zip
  • Localização: /var/www/example.com/uploaded_file.zip - não acessível (mesmo usando example.com /../ uploaded_file.zip)

Em essência, um arquivo acima da raiz do documento não será acessível através de um navegador, entretanto, a maioria das configurações do PHP permitirá que seu código leia o arquivo e entregue-o (restrições a isso são geralmente um resultado de open_basedir )

Em alguns cenários, pode ser preferível ter seus arquivos sob a raiz do documento. Para fazer isso e ainda impedir o acesso externo (direto), você usará a diretiva internal . Por exemplo:

localização / uploads {     interno; }

Agora, todos os arquivos colocados em /var/www/example.com/public_html/uploads são acessíveis internamente (ou seja, não podem ser acessados por meio de um navegador, mas podem ser acessados por seus scripts PHP). Se desejar, você também pode configurar um alias no local / uploads, para que outro caminho também possa ser usado para fazer referência a ele.

Neste ponto, seus arquivos não estão diretamente acessíveis, mas seus scripts ainda podem atendê-los.

Autenticação do usuário e PHP:

Considere o seguinte design básico: Um usuário pode acessar um arquivo diretamente ou acessar a página de login. Se eles tentarem acessar um arquivo diretamente e estiverem logados (e tiverem permissão), o arquivo será baixado, caso contrário, eles serão exibidos na tela de login. Para carregar um arquivo, um usuário precisa estar logado.

Digamos que seu script de download (a página que entregará o arquivo ao usuário) seja chamado de 'download.php'. Um URL típico pode ser example.com/download.php?file=uploaded_file.zip. É bem provável que você não queira que seus URLs incluam o nome do arquivo php. Para evitar isso, você pode configurar uma regra de reescrita em sua configuração nginx que apontará outro local (digamos / arquivos) em seu script. Adicione à sua configuração do nginx:

rewrite ^/files/(.*) /download.php?file=$1 last;

(O que equivale a mudar o caminho requisitado de qualquer requisição começando com / files, e capturar tudo após o / e passá-lo como um parâmetro de consulta para o seu arquivo php);

Agora, seu arquivo pode ser acessado via: example.com/files/uploaded_file.zip (que redireciona internamente para o seu script php).

Seu arquivo PHP (download.php) agora faz o seguinte:

  • Iniciar a sessão
  • Se o usuário estiver logado, prossiga, caso contrário, redirecione para uma página de login, passando o arquivo de destino como parte da string de consulta
  • Consulte seu banco de dados (por exemplo, MySQL) para ver se o usuário pode acessar esse arquivo
    • Se o usuário tiver permissão, prossiga, caso contrário, redirecione para uma página de erro
  • Produza os cabeçalhos necessários (Content-Type, Content-Disposition, etc) e defina:

    X-Accel-Redirect: /uploads/uploaded_file.zip;

Note que você pode fazer o download real do PHP (por exemplo, usando readfile ) - é apenas um pouco mais eficiente, especialmente para arquivos grandes) para fazer isso via nginx. Além disso, apesar do usuário aparecer para acessar o arquivo diretamente, internamente, ele está passando pelo PHP, que está autenticando-os antes de permitir que eles continuem.

URL -> nginx (redirect to PHP) -> PHP (authenticate) -> nginx (serve file)

No lado do envio das coisas, você vai move_uploaded_file para /var/www/example.com/public_html/uploads (que é protegido pela diretiva 'interna' e, portanto, os arquivos não podem ser acessados diretamente), e salvar permissões no seu banco de dados.

    
por 19.11.2011 / 08:31