Разрешения на обслуживание временных файлов

8

У меня есть система (веб-приложение), которая извлекает вложения файлов из сторонней системы через SOAP. Это, в свою очередь, наша система, созданная в виде файлов в каталоге.

Когда пользователь системы (аутентифицируемый через ldap) делает запрос к моему приложению, чтобы получить одно из этих вложений:

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.  

Во-первых, это хороший подход?

Есть ли лучший способ обслуживать файлы, которые не будут находиться на сервере после загрузки вложения (задание cron будет часто очищать каталог)?

Во-вторых, есть ли способ, которым я могу обслуживать файлы через apache, не сохраняя их в корне сети?

В-третьих, как мне обеспечить разрешения для этих файлов, чтобы не любой пользователь мог загрузить только любое вложение?

Наша установка:

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

РЕДАКТИРОВАТЬ: код для приложения в случае, если кому-то любопытно.

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


?>
Крис
источник
Это, вероятно, принадлежит StackOverflow
Джон Конде

Ответы:

2

Во-первых, это хороший подход?

Звучит хорошо для меня. Просто убедитесь, что вы аутентифицируете пользователя, прежде чем пройти через все это.

Есть ли лучший способ обслуживать файлы, которые не будут находиться на сервере после загрузки вложения (задание cron будет часто очищать каталог)?

Во-вторых, есть ли способ, которым я могу обслуживать файлы через apache, не сохраняя их в корне сети?

Поместите файлы вне webroot. Затем с помощью PHP передайте файл через скрипт. Таким образом, никто не сможет напрямую связаться с файлом и обойти ваши элементы управления. (Естественно, убедитесь, что скрипт, который делает это, только после проверки, что у пользователя есть разрешение на получение этого файла).

Пример 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;
?>

В-третьих, как мне обеспечить разрешения для этих файлов, чтобы не любой пользователь мог загрузить только любое вложение?

Заставьте пользователей войти в систему, чтобы получить их файлы. Затем вы можете установить переменную сеанса, идентифицирующую их как разрешенные для загрузки. Убедитесь, что ваши скрипты аутентифицируют их на каждой странице этого процесса.

Джон Конде
источник
Это отличное объяснение! Спасибо. Исходя из вашего предложения, было бы лучше хранить эти файлы вне webroot таким образом, чтобы мне не приходилось беспокоиться о прямой ссылке / доступе к файлам, а просто обслуживал их на основе php-страницы с логикой, аналогичной приведенной выше, для проверки аутентификация пользователя перед подачей файла. Приветствия
Крис
@John Conde Я заметил специфический тип контента как «application / octet-stream», так что это будет работать с любым типом файла? Это не работает и не определяет тип mime-содержимого. Например, у меня есть PDF-файл, который я могу вытащить, и знаю, что это хороший PDF-файл, но когда я делаю это по моде, которую вы представляете, я получаю «Тип файла простой текстовый документ (text / plain) не поддерживается».
Крис
Я так считаю. Если этого не произойдет, все, что вам нужно сделать, это изменить эту часть на правильный тип пантомимы. Но я уверен, что это будет работать для любого типа файла.
Джон Конде
По какой-то причине я могу перейти к uploads / filename.pdf, но скрипт php не может обработать файл, используя application / octet-stream или application / pdf для этого конкретного случая.
Крис
Какая у вас ошибка? Убедитесь, что скрипт может найти файл, поскольку путь может быть где-то неверным.
Джон Конде