Quyền phục vụ các tập tin tạm thời


8

Tôi có một hệ thống (ứng dụng dựa trên web) để kéo tệp đính kèm từ hệ thống bên thứ 3 thông qua SOAP. Chúng lần lượt được bật trên hệ thống của chúng tôi được tạo dưới dạng tệp trong một thư mục.

Khi người dùng hệ thống (được xác thực qua ldap) đưa ra yêu cầu đến ứng dụng của tôi để lấy một trong các tệp đính kèm sau:

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.  

Trước hết, đây có phải là một cách tiếp cận tốt?

Có cách nào tốt hơn để phục vụ các tệp không cư trú trên máy chủ nhiều sau khi tải xuống tệp đính kèm (công việc cron sẽ dọn sạch thư mục thường xuyên)?

Thứ hai, có cách nào tôi có thể phục vụ các tệp thông qua apache mà không lưu trữ chúng trong thư mục gốc không?

Thứ ba, làm cách nào để tôi thực thi quyền trên các tệp này để không phải bất kỳ người dùng nào cũng có thể tải xuống bất kỳ tệp đính kèm nào?

Thiết lập của chúng tôi:

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

EDIT: Mã để phục vụ tệp đính kèm trong trường hợp bất kỳ ai cũng tò mò.

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


?>

Điều này có lẽ thuộc về StackOverflow
John Conde

Câu trả lời:


2

Trước hết, đây có phải là một cách tiếp cận tốt?

Âm thanh tốt với tôi. Chỉ cần chắc chắn rằng bạn xác thực người dùng trước khi trải qua tất cả điều đó.

Có cách nào tốt hơn để phục vụ các tệp không cư trú trên máy chủ nhiều sau khi tải xuống tệp đính kèm (công việc cron sẽ dọn sạch thư mục thường xuyên)?

Thứ hai, có cách nào tôi có thể phục vụ các tệp thông qua apache mà không lưu trữ chúng trong thư mục gốc không?

Đặt các tập tin bên ngoài webroot. Sau đó, sử dụng PHP vượt qua các tập tin mặc dù một tập lệnh. Bằng cách đó, không ai có thể liên kết trực tiếp đến tệp và bỏ qua các điều khiển của bạn. (Đương nhiên đảm bảo tập lệnh chỉ thực hiện việc này sau khi xác minh người dùng có quyền truy xuất tệp đó).

Mẫu 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;
?>

Thứ ba, làm cách nào để tôi thực thi quyền trên các tệp này để không phải bất kỳ người dùng nào cũng có thể tải xuống bất kỳ tệp đính kèm nào?

Làm cho người dùng đăng nhập để lấy các tập tin của họ. Sau đó, bạn có thể đặt biến phiên xác định chúng là được phép tải xuống. Hãy chắc chắn rằng tập lệnh của bạn xác thực chúng trên mỗi trang của quy trình này.


Đây là một lời giải thích tuyệt vời! Cảm ơn. Dựa trên đề xuất của bạn, tốt hơn là lưu trữ các tệp này bên ngoài webroot theo cách mà tôi không phải lo lắng về liên kết / truy cập trực tiếp vào các tệp và chỉ phục vụ chúng dựa trên trang php có logic tương tự như trên để xác minh xác thực người dùng trước khi phục vụ tập tin. Chúc mừng
Chris

@John Conde Tôi nhận thấy loại nội dung cụ thể là "application / octet-stream" vì vậy điều này sẽ hoạt động với bất kỳ loại tệp nào? Điều này không hoạt động, cũng không chỉ định loại mime nội dung. Ví dụ: tôi có một pdf ngồi ở đó mà tôi có thể kéo và biết đó là một pdf tốt nhưng khi tôi phục vụ nó thông qua thời trang bạn trình bày, tôi nhận được "Tài liệu văn bản thuần tuý (văn bản / văn bản) không được hỗ trợ".
Chris

Tôi cũng tin như thế. Nếu không, tất cả những gì bạn cần làm là thay đổi phần đó thành loại mime thích hợp. Nhưng tôi khá chắc chắn rằng nó sẽ hoạt động cho bất kỳ loại tập tin.
John Conde

Vì một số lý do, tôi có thể goto tải lên / filename.pdf nhưng tập lệnh php không thể phục vụ tệp bằng ứng dụng / octet-stream hoặc application / pdf cho trường hợp cụ thể này.
Chris

lỗi gì bạn nhận được? Xác minh rằng tập lệnh có thể tìm thấy tệp vì đường dẫn có thể không chính xác ở đâu đó.
John Conde
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.