Acesse um arquivo em PHP através de um link simbólico de um usuário que normalmente não tem permissão

4

Eu tenho este site, onde se o usuário envia um formulário, um script python é executado através de uma página php, e o script python cria um arquivo zip e deve oferecê-lo ao usuário para download através de um link. O arquivo pode ser enorme (alguns GB).

Como estou trabalhando em um servidor universitário, estou estritamente vinculado às regras e aos recursos do servidor. Aqui está o problema:

O site é armazenado em /data/mywebsite , que possui espaço em disco limitado. É claro que isso é de propriedade de www-data , pois é acessado principalmente pelo meu servidor Apache.

Recebi oferta de 1 TB de armazenamento em /experimentdata/ , que é ACESSÍVEL APENAS por um usuário específico e único, digamos theuser . Isso ocorre porque essa pasta é uma montagem do samba que pode ser acessada por um ID de usuário único e específico.

Para criar o arquivo em /experimentdata , eu uso um comando sudo -u theuser que criará o arquivo /experimentdata/downloadme.zip como usuário theuser . Agora meu problema é: Como posso oferecer este arquivo através de um link para download através do Apache?

Eu pensei em usar um link simbólico que eu coloquei, por exemplo, /data/mywebsite/download/downloadme.zip . O problema é que o usuário www-data não tem absolutamente permissão para ler o arquivo!

Como posso deixar o usuário fazer o download do arquivo /experimentdata/downloadme.zip com o usuário www-data através do usuário theuser ?

Gostaria de dizer explicitamente que envolver sudo -u theuser é absolutamente aceitável. Mas eu não sei como fazer um link disso para algum lugar fora da pasta do meu site.

PS: Se você precisar de alguma informação adicional, por favor, pergunte.

    
por The Quantum Physicist 07.11.2015 / 20:59

1 resposta

2

Acho que a coisa a fazer é que o php / python retorne os dados diretamente, em vez de apache . Seu código pode fazer a mesma coisa que apache faz. Na minha experiência, isso é muito melhor do que abrir outro diretório e / ou usar sudo ou alterar as permissões de arquivo para apache , etc.

Se o programa produzir o arquivo grande mais rápido que a conexão com a Internet, você poderá transmitir os dados diretamente do seu programa, o que elimina o arquivo de dados extra e o código para gerenciá-lo e os mecanismos para lembrá-lo.

Esta resposta no Stack Overflow mostra como o código funciona em php . link .

Para programas que serão chamados dessa maneira, elimine todas as saídas stderr stream e certifique-se de que o código de retorno do processo python reflita com precisão o sucesso ou a falha do processo.

Os exemplos abaixo mostram as chamadas popen() que você usaria no cenário de exemplo acima de stackoverflow. Eu prefixei exec 2>/dev/null; no comando shell. Isso garante que nenhuma saída vá para o erro padrão, mesmo a partir do próprio shell, porque ter dados chegando em stderr e stdout pode ser uma fonte de impasses com popen() .

Se você quiser baixar o arquivo do disco para o seu usuário:

$fp = popen('exec 2>/dev/null; sudo -u theuser cat yourfile.zip', 'r');

Se você deseja baixar os dados do processo ativo:

$fp = popen('exec 2>/dev/null; sudo yourpythonscript arg argN', 'r');

Essas linhas de comando são comandos shell e precisam ser citadas apropriadamente para meta-caracteres do shell.

No segundo método, o servidor começaria a enviar os dados imediatamente. Quando o usuário envia com sucesso o formulário, ele vê imediatamente uma caixa de diálogo "salvar como" no navegador. Assim que o usuário seleciona o arquivo de saída, seu script php transmite os dados diretamente através do fio e para o arquivo remoto.

O script python deve imprimir somente os dados zip na saída padrão e retornar um código de saída que represente com precisão o sucesso ou a falha do processo zip. Em python , o script deve gravar a saída em sys.stdout , por exemplo zf = ZipFile(sys.stdout, ... .

É fundamental chamar pclose() e verificar o valor de retorno , porque essa será a única maneira de saber se o zip foi bem-sucedido ou não. Se pclose() retornar algo diferente de 0, algo está errado.

Como o arquivo é tratado pelo cliente depende das configurações desses response headers e de outros: content-type: , content-encoding: e content-disposition: Consulte: link , veja as informações de response-header e entity-header .

    
por 07.11.2015 / 23:15