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

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

Eu tenho este site, onde se o usuário enviar 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 capacidades do servidor. Aqui está o problema:

O site está armazenado em /data/mywebsite, que possui espaço em disco limitado. É claro que isso é propriedade de, www-datapois é acessível principalmente pelo meu servidor Apache.

Me oferecem 1 TB de armazenamento /experimentdata/, que só é ACESSÍVEL por um único usuário específico, por exemplo theuser. Isso ocorre porque esta pasta é uma montagem samba que pode ser acessada por um ID de usuário único e específico.

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

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

Como posso permitir que o usuário baixe o arquivo /experimentdata/downloadme.zipcom o usuário www-dataatravés do usuário theuser?

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

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

Responder1

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

Se o programa produzir o arquivo grande mais rápido do 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.https://stackoverflow.com/a/4357904/5484716.

Para programas que serão chamados dessa forma, elimine toda stderra saída do fluxo e certifique-se de que o código de retorno do seu processo python reflita com precisão o sucesso ou a falha do processo.

Os exemplos abaixo mostram as popen()chamadas que você usaria no cenário de exemplo acima do stackoverflow. Anexei exec 2>/dev/null;o comando shell. Isso garante que nenhuma saída vá para o erro padrão, mesmo do próprio shell, porque ter dados chegando em ambos stderrpode stdoutser uma fonte de conflitos com popen().

Se você deseja 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 comandosãocomandos shell e precisam ser citados apropriadamente para metacaracteres shell.

No segundo método, o servidor começaria a enviar os dados imediatamente. Quando o usuário envia o formulário com êxito, ele vê imediatamente uma caixa de diálogo "salvar como" em seu navegador. Assim que o usuário seleciona o arquivo de saída, seu phpscript transmite os dados diretamente pela rede e para o arquivo remoto.

O pythonscript deve imprimirapenasos dados zip na saída padrão e retorna um código de saída que representa com precisão o sucesso ou a falha do processo zip. No pythonscript deve-se escrever a saída em sys.stdout, por exemplo zf = ZipFile(sys.stdout, ....

É fundamental ligar 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.

A forma como o arquivo é tratado pelo cliente depende das configurações destes response headerse de outros: content-type:, content-encoding:, e content-disposition: Veja:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, veja o response-headere as entity-headerinformações.

informação relacionada