Acceder a un archivo en PHP a través de un enlace simbólico de un usuario que normalmente no tiene permiso

Acceder a un archivo en PHP a través de un enlace simbólico de un usuario que normalmente no tiene permiso

Tengo este sitio web, donde si el usuario envía un formulario, se ejecuta una secuencia de comandos de Python a través de una página PHP, y la secuencia de comandos de Python crea un archivo zip y debe ofrecérselo al usuario para que lo descargue a través de un enlace. El archivo podría ser enorme (unos pocos GB).

Como trabajo en un servidor universitario, estoy estrictamente sujeto a las reglas y capacidades de su servidor. Aquí está el problema:

El sitio web se almacena en /data/mywebsite, que tiene un espacio en disco limitado. Por supuesto, esto es propiedad de, www-dataya que mi servidor Apache puede acceder a él principalmente.

Me ofrecen 1 TB de almacenamiento en /experimentdata/, al que SÓLO puede ACCEDER un usuario único y específico, digamos theuser. Esto se debe a que esta carpeta es un montaje de samba al que se puede acceder mediante una identificación de usuario única y específica.

Para crear el archivo en /experimentdata, uso un sudo -u theusercomando que creará el archivo /experimentdata/downloadme.zipcomo usuario theuser. Ahora mi problema es: ¿Cómo puedo ofrecer este archivo a través de un enlace para su descarga a través de Apache?

Pensé en usar un enlace simbólico que puse, por ejemplo /data/mywebsite/download/downloadme.zip,. ¡El problema con esto es que el usuario www-datano tiene ningún permiso para leer el archivo!

¿Cómo puedo permitir que el usuario descargue el archivo /experimentdata/downloadme.zipcon el usuario www-dataa través del usuario theuser?

Me gustaría decir explícitamente que involucrarse sudo -u theuserestá absolutamente bien. Pero no sé cómo crear un enlace a partir de eso a algún lugar fuera de la carpeta de mi sitio web.

PD: Si necesita alguna información adicional, por favor pregunte.

Respuesta1

Creo que lo que hay que hacer es que php/ pythondevuelva los datos directamente en lugar de apache. Su código puede hacer lo mismo que apachehace. En mi experiencia, esto es mucho mejor que abrir otro directorio y/o usar sudo, o cambiar los permisos de archivos apache, etc.

Si el programa produce el archivo grande más rápido que la conexión a Internet, entonces puede transmitir los datos directamente desde su programa, lo que elimina el archivo de datos adicional y el código para administrarlo y los mecanismos para recordarlo.

Esta respuesta en Stack Overflow muestra cómo funciona el código php.https://stackoverflow.com/a/4357904/5484716.

Para los programas que se llamarán de esta manera, elimine toda stderrla salida de flujo y asegúrese de que el código de retorno de su proceso de Python refleje con precisión el éxito o el fracaso del proceso.

Los siguientes ejemplos muestran las popen()llamadas que usaría en el escenario de ejemplo anterior desde stackoverflow. Lo he antepuesto exec 2>/dev/null;al comando de shell. Esto garantiza que ninguna salida genere un error estándar, incluso desde el propio shell, porque tener datos provenientes de ambos stderrpuede stdoutser una fuente de interbloqueos con popen().

Si desea descargar el archivo de disco a su usuario:

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

Si desea descargar los datos del proceso activo:

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

Estas líneas de comandosoncomandos de shell y deben citarse adecuadamente para los metacaracteres de shell.

En el segundo método, el servidor comenzaría a enviar los datos inmediatamente. Cuando el usuario envía correctamente el formulario, ve inmediatamente un cuadro de diálogo "guardar como" en su navegador. Tan pronto como el usuario selecciona el archivo de salida, su phpsecuencia de comandos transmite los datos directamente a través del cable y al archivo remoto.

El pythonguión debería imprimirse.sololos datos zip en la salida estándar y devuelve un código de salida que representa con precisión el éxito o el fracaso del proceso zip. En pythonel script se debe escribir la salida sys.stdout, por ejemplo zf = ZipFile(sys.stdout, ....

Es fundamental llamar pclose()y verificar el valor de retorno., porque esa será la única forma de saber si el zip tuvo éxito o no. Si pclose()devuelve algo distinto de 0, algo anda mal.

La forma en que el cliente maneja el archivo depende de la configuración de estos response headersy otros: content-type:, content-encoding:y content-disposition: Consulte:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, mira el response-headery la entity-headerinformación.

información relacionada