Tengo un sistema (aplicación basada en web) que extrae archivos adjuntos de un sistema de terceros a través de SOAP. Estos a su vez se crean en nuestro sistema como archivos en un directorio.
Cuando un usuario del sistema (autenticado a través de ldap) realiza una solicitud a mi aplicación para recuperar uno de estos archivos adjuntos:
1. I request it via soap
2. Process the response to build the file on our system
3. Redirect user to the location so they can download the file.
En primer lugar, ¿es este un buen enfoque?
¿Hay una mejor manera de servir archivos que no residirán en el servidor mucho después de la descarga del archivo adjunto (el trabajo cron limpiará el directorio de vez en cuando)?
En segundo lugar, ¿hay alguna forma en que pueda servir archivos a través de apache sin almacenarlos en la raíz web?
En tercer lugar, ¿cómo hago cumplir los permisos en estos archivos para que no cualquier usuario pueda descargar cualquier archivo adjunto?
Nuestra Configuración:
linux
apache
php - soap libraries for communication
seperate LDAP for authentication
3rd party soap server (where attachments come from)
EDITAR: El código para servir el archivo adjunto en caso de que alguien tenga curiosidad.
<?php
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
//require global definitions
require_once("includes/globals.php");
//validate the user before continuing
isValidUser();
$subTitle = "Attachment";
$attachmentPath = "/var/www/html/DEVELOPMENT/serviceNow/selfService/uploads/";
if(isset($_GET['id']) and !empty($_GET['id'])){
//first lookup attachment meta information
$a = new Attachment();
$attachment = $a->get($_GET['id']);
//filename will be original file name with user name.n prepended
$fileName = $attachmentPath.$_SESSION['nameN'].'-'.$attachment->file_name;
//instantiate new attachmentDownload and query for attachment chunks
$a = new AttachmentDownload();
$chunks= $a->getRecords(array('sys_attachment'=>$_GET['id'], '__order_by'=>'position'));
$fh = fopen($fileName.'.gz','w');
// read and base64 encode file contents
foreach($chunks as $chunk){
fwrite($fh, base64_decode($chunk->data));
}
fclose($fh);
//open up filename for writing
$fh = fopen($fileName,'w');
//open up filename.gz for extraction
$zd = gzopen($fileName.'.gz', "r");
//iterate over file and write contents
while (!feof($zd)) {
fwrite($fh, gzread($zd, 60*57));
}
fclose($fh);
gzclose($zd);
unlink($fileName.'.gz');
$info = pathinfo($fileName);
header('Content-Description: File Transfer');
header('Content-Type: '.Mimetypes::get($info['extension']));
header('Content-Disposition: attachment; filename=' . basename($fileName));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($fileName));
ob_clean();
flush();
readfile($fileName);
exit();
}else{
header("location: ".$links['status']."?".urlencode("item=incident&action=view&status=-1&place=".$links['home']));
}
?>
Respuestas:
Suena bien para mi. Solo asegúrese de autenticar al usuario antes de pasar por todo eso.
Ponga los archivos fuera del webroot. Luego, usando PHP, pasa el archivo a través de un script. De esa manera, nadie puede vincular el archivo directamente y omitir sus controles. (Naturalmente, asegúrese de que el script que hace esto solo después de verificar que el usuario tenga permiso para recuperar ese archivo).
PHP de muestra:
Haga que los usuarios inicien sesión para recuperar sus archivos. Luego, puede establecer una variable de sesión que los identifique como permitidos para descargar. Asegúrese de que sus scripts los autentiquen en cada página de este proceso.
fuente