Autorisations pour servir des fichiers temporaires


8

J'ai un système (application Web) qui extrait les pièces jointes d'un système tiers via SOAP. Ce sont à leur tour notre système créé sous forme de fichiers dans un répertoire.

Lorsqu'un utilisateur du système (authentifié via ldap) fait une demande à mon application pour récupérer l'une de ces pièces jointes:

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.  

Tout d'abord, est-ce une bonne approche?

Existe-t-il un meilleur moyen de servir des fichiers qui ne résideront pas sur le serveur bien après le téléchargement des pièces jointes (le travail cron nettoiera le répertoire de temps en temps)?

Deuxièmement, existe-t-il un moyen de servir des fichiers via Apache sans les stocker dans la racine Web?

Troisièmement, comment puis-je appliquer des autorisations sur ces fichiers afin que tout utilisateur ne puisse télécharger que n'importe quelle pièce jointe?

Notre configuration:

linux
apache
php - soap libraries for communication 
seperate LDAP for authentication
3rd party soap server (where attachments come from) 

EDIT: Le code pour servir la pièce jointe au cas où quelqu'un serait curieux.

    <?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']));   
}


?>

Cela appartient probablement à StackOverflow
John Conde

Réponses:


2

Tout d'abord, est-ce une bonne approche?

Ça me semble bien. Assurez-vous simplement d'authentifier l'utilisateur avant de passer par tout cela.

Existe-t-il un meilleur moyen de servir des fichiers qui ne résideront pas sur le serveur bien après le téléchargement des pièces jointes (le travail cron nettoiera le répertoire de temps en temps)?

Deuxièmement, existe-t-il un moyen de servir des fichiers via Apache sans les stocker dans la racine Web?

Mettez les fichiers en dehors de la racine Web. Ensuite, en utilisant PHP, passez le fichier via un script. De cette façon, personne ne peut se lier directement au fichier et contourner vos contrôles. (Naturellement, assurez-vous que le script qui fait cela uniquement après avoir vérifié que l'utilisateur est autorisé à récupérer ce fichier).

Exemple de PHP:

<?php
    if (!isset($_SESSION['authenticated']))
    {
        exit;
    }
    $file = '/path/to/file/outside/www/secret.pdf';

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename($file));
    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($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
?>

Troisièmement, comment puis-je appliquer des autorisations sur ces fichiers afin que tout utilisateur ne puisse télécharger que n'importe quelle pièce jointe?

Demandez aux utilisateurs de se connecter pour récupérer leurs fichiers. Ensuite, vous pouvez définir une variable de session les identifiant comme étant autorisés à télécharger. Assurez-vous que vos scripts les authentifient sur chaque page de ce processus.


Ceci est une excellente explication! Merci. Sur la base de votre suggestion, il serait préférable de stocker ces fichiers en dehors de la racine Web de cette façon, je n'ai pas à me soucier du lien direct / de l'accès aux fichiers et de simplement les servir sur la base d'une page php avec une logique similaire à celle ci-dessus pour vérifier la authentification de l'utilisateur avant de servir le fichier. Cheers
Chris

@John Conde J'ai remarqué un type de contenu spécifique comme "application / octet-stream", donc cela fonctionnera avec n'importe quel type de fichier? Cela ne fonctionne pas, pas plus que la spécification du type MIME du contenu. Par exemple, j'ai un pdf assis que je peux tirer et je sais que c'est un bon pdf mais quand je le sers via la mode que vous présentez, je reçois "Le type de fichier texte en clair (text / plain) n'est pas supporté".
Chris

Je le crois. Si ce n'est pas le cas, tout ce que vous devez faire est de changer cette partie pour le type de mime approprié. Mais je suis presque sûr que cela fonctionnera pour tout type de fichier.
John Conde

Pour une raison quelconque, je peux aller sur uploads / filename.pdf mais le script php ne peut pas servir le fichier en utilisant soit application / octet-stream ou application / pdf pour ce cas spécifique.
Chris

Quelle erreur obtenez-vous? Vérifiez que le script peut trouver le fichier car le chemin d'accès peut être incorrect quelque part.
John Conde
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.