2016-07-21 28 views
15

Tôi không biết điều này có xảy ra hay không, nhưng tôi sẽ thử.Kịch bản tải lên hình ảnh bảo mật đầy đủ

Trong giờ qua tôi đã nghiên cứu về an toàn tải lên hình ảnh. Tôi đã học được rằng có rất nhiều chức năng để kiểm tra việc tải lên.

Trong dự án của tôi, tôi cần phải an toàn với hình ảnh được tải lên. Cũng có thể có một số lượng thực sự lớn và nó có thể đòi hỏi nhiều băng thông, vì vậy việc mua một API không phải là một lựa chọn.

Vì vậy, tôi đã quyết định nhận một tập lệnh PHP đầy đủ để tải lên hình ảnh an toàn thực sự. Tôi cũng nghĩ rằng nó sẽ giúp ích cho nhiều người ở ngoài kia, bởi vì không thể tìm được một người thực sự an toàn. Nhưng tôi không phải là chuyên gia về php, vì vậy nó thực sự đau đầu cho tôi để thêm một số chức năng, vì vậy tôi sẽ yêu cầu cộng đồng này giúp đỡ để tạo ra một kịch bản đầy đủ của REALLY an toàn hình ảnh tải lên.

Các chủ đề thực sự tuyệt vời ở đây (tuy nhiên, họ chỉ nói những gì cần thiết để thực hiện thủ thuật, nhưng không phải cách thực hiện điều này, và như tôi đã nói tôi không phải là chủ trên PHP, vì vậy tôi không thể để làm điều này tất cả bởi bản thân mình): PHP image upload security check list https://security.stackexchange.com/questions/32852/risks-of-a-php-image-upload-form

nói tóm lại, họ đang nói rằng đây là những gì cần thiết để tải lên hình ảnh an ninh (tôi sẽ trích dẫn từ trang ở trên):

  • Tắt PHP chạy bên trong thư mục tải lên bằng cách sử dụng .httacce ss
  • Không cho phép tải lên nếu tên tệp chứa chuỗi "php".
  • Chỉ cho phép các tiện ích mở rộng: jpg, jpeg, gif và png.
  • Chỉ cho phép loại tệp hình ảnh.
  • Không cho phép hình ảnh có hai loại tệp.
  • Thay đổi tên hình ảnh. Tải lên thư mục con không phải thư mục gốc.

Ngoài ra:

  • lại quá trình hình ảnh sử dụng GD (hoặc Imagick) và lưu hình ảnh xử lý. Tất cả những người khác chỉ là nhàm chán cho tin tặc "
  • Như đã chỉ ra, sử dụng move_uploaded_file() cho bất kỳ tải lên nào"
  • Nhân tiện, bạn muốn rất hạn chế về thư mục tải lên của mình. Những địa điểm này là một trong những góc tối nơi nhiều người khai thác
    xảy ra. Điều này hợp lệ đối với mọi loại tệp tải lên và mọi ngôn ngữ lập trình
    ngôn ngữ/máy chủ. Kiểm tra
    https://www.owasp.org/index.php/Unrestricted_File_Upload
  • Level 1: Kiểm tra phần mở rộng (file mở rộng kết thúc với)
  • Level 2: Kiểm tra kiểu MIME ($ file_info = getimagesize ($ _ FILES [ 'image_file']; $ file_mime = $ file_info [' mime '];)
  • Cấp 3: Đọc 100 byte đầu tiên và kiểm tra xem chúng có bất kỳ byte nào trong phạm vi sau đây không: ASCII 0-8, 12-31 (thập phân)
  • Cấp 4: Kiểm tra số ma thuật trong tiêu đề (10-20 byte đầu tiên của tệp).Bạn có thể tìm thấy một số các tập tin tiêu đề byte từ đây:
    http://en.wikipedia.org/wiki/Magic_number_%28programming%29#Examples
  • Bạn có thể muốn chạy "is_uploaded_file" trên $ _FILES [ 'my_files'] [ 'tmp_name'] là tốt. Xem
    http://php.net/manual/en/function.is-uploaded-file.php

Dưới đây là một phần quan trọng của nó, nhưng vẫn còn đó không phải là tất cả. (Nếu bạn biết một cái gì đó nhiều hơn mà có thể giúp đỡ để làm cho tải lên thậm chí safier, xin vui lòng chia sẻ.)

NÀY LÀ GÌ CHÚNG TÔI GOT VỚI DOANH NGHIỆP

  • Main PHP:

    function uploadFile ($file_field = null, $check_image = false, $random_name = false) { 
    
    //Config Section  
    //Set file upload path 
    $path = 'uploads/'; //with trailing slash 
    //Set max file size in bytes 
    $max_size = 1000000; 
    //Set default file extension whitelist 
    $whitelist_ext = array('jpeg','jpg','png','gif'); 
    //Set default file type whitelist 
    $whitelist_type = array('image/jpeg', 'image/jpg', 'image/png','image/gif'); 
    
    //The Validation 
    // Create an array to hold any output 
    $out = array('error'=>null); 
    
    if (!$file_field) { 
        $out['error'][] = "Please specify a valid form field name";   
    } 
    
    if (!$path) { 
        $out['error'][] = "Please specify a valid upload path";    
    } 
    
    if (count($out['error'])>0) { 
        return $out; 
    } 
    
    //Make sure that there is a file 
    if((!empty($_FILES[$file_field])) && ($_FILES[$file_field]['error'] == 0)) { 
    
    // Get filename 
    $file_info = pathinfo($_FILES[$file_field]['name']); 
    $name = $file_info['filename']; 
    $ext = $file_info['extension']; 
    
    //Check file has the right extension   
    if (!in_array($ext, $whitelist_ext)) { 
        $out['error'][] = "Invalid file Extension"; 
    } 
    
    //Check that the file is of the right type 
    if (!in_array($_FILES[$file_field]["type"], $whitelist_type)) { 
        $out['error'][] = "Invalid file Type"; 
    } 
    
    //Check that the file is not too big 
    if ($_FILES[$file_field]["size"] > $max_size) { 
        $out['error'][] = "File is too big"; 
    } 
    
    //If $check image is set as true 
    if ($check_image) { 
        if (!getimagesize($_FILES[$file_field]['tmp_name'])) { 
        $out['error'][] = "Uploaded file is not a valid image"; 
        } 
    } 
    
    //Create full filename including path 
    if ($random_name) { 
        // Generate random filename 
        $tmp = str_replace(array('.',' '), array('',''), microtime()); 
    
        if (!$tmp || $tmp == '') { 
        $out['error'][] = "File must have a name"; 
        }  
        $newname = $tmp.'.'.$ext;         
    } else { 
        $newname = $name.'.'.$ext; 
    } 
    
    //Check if file already exists on server 
    if (file_exists($path.$newname)) { 
        $out['error'][] = "A file with this name already exists"; 
    } 
    
    if (count($out['error'])>0) { 
        //The file has not correctly validated 
        return $out; 
    } 
    
    if (move_uploaded_file($_FILES[$file_field]['tmp_name'], $path.$newname)) { 
        //Success 
        $out['filepath'] = $path; 
        $out['filename'] = $newname; 
        return $out; 
    } else { 
        $out['error'][] = "Server Error!"; 
    } 
    
    } else { 
        $out['error'][] = "No file uploaded"; 
        return $out; 
    }  
    } 
    
    
    if (isset($_POST['submit'])) { 
    $file = uploadFile('file', true, true); 
    if (is_array($file['error'])) { 
        $message = ''; 
        foreach ($file['error'] as $msg) { 
        $message .= '<p>'.$msg.'</p>';  
    } 
    } else { 
    $message = "File uploaded successfully".$newname; 
    } 
    echo $message; 
    } 
    
  • Và biểu mẫu:

    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data" name="form1" id="form1"> 
    <input name="file" type="file" id="imagee" /> 
    <input name="submit" type="submit" value="Upload" /> 
    </form> 
    

Vì vậy, những gì tôi yêu cầu là trợ giúp bằng cách đăng đoạn mã giúp tôi (và mọi người khác) làm cho Kịch bản tải lên hình ảnh này trở nên cực kỳ an toàn. Hoặc bằng cách chia sẻ/tạo tập lệnh đầy đủ với tất cả các đoạn mã được thêm vào.

+4

Ai đó có thể cho biết lý do khiến bài đăng của tôi bị giảm giá? Nhìn vào quan điểm và cách hữu ích của chủ đề này là dành cho người khác, tôi không nghĩ rằng điều này là đúng. – Simon

+0

Vì tôi tiếp tục nhận được upvotes trên câu trả lời của tôi về điều này, hãy để tôi giải thích những downvotes về câu hỏi của bạn: Stack tràn là một nơi để tìm sự giúp đỡ nếu bạn có vấn đề với mã của bạn. Đây không phải là nơi để tìm kiếm sự cải thiện về mã làm việc ([Code Review] (http://codereview.stackexchange.com/) là trang web cho điều đó), và cũng không phải là nơi để tìm kiếm hoặc yêu cầu hướng dẫn. Đơn giản chỉ vì (như bạn thấy), nó phải viết một nửa cuốn sách để đưa ra một câu trả lời tốt và thích hợp. Số lượt xem đơn giản chỉ vì bạn đã cung cấp tiền thưởng cho nó. Không phải vì tất cả mọi người cần điều này :) – icecub

+1

@icecub Tôi chắc chắn vẫn còn những người đang tìm kiếm câu trả lời này và những người rất vui vì bạn đã trả lời nó. – Simon

Trả lời

39

Khi bạn bắt đầu làm việc trên tập lệnh tải lên hình ảnh an toàn, có nhiều điều cần cân nhắc. Bây giờ tôi không có nơi nào gần một chuyên gia về điều này, nhưng tôi đã được yêu cầu phát triển điều này một lần trong quá khứ. Tôi sẽ đi qua toàn bộ quá trình tôi đã trải qua ở đây để bạn có thể theo dõi. Đối với điều này tôi sẽ bắt đầu với một hình thức html rất cơ bản và kịch bản php xử lý các tập tin. hình thức

HTML:

<form name="upload" action="upload.php" method="POST" enctype="multipart/form-data"> 
    Select image to upload: <input type="file" name="image"> 
    <input type="submit" name="upload" value="upload"> 
</form> 

PHP file:

<?php 
$uploaddir = 'uploads/'; 

$uploadfile = $uploaddir . basename($_FILES['image']['name']); 

if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadfile)) { 
    echo "Image succesfully uploaded."; 
} else { 
    echo "Image uploading failed."; 
} 
?> 

Vấn đề đầu tiên: File types
Những kẻ tấn công không cần phải sử dụng các hình thức trên trang web của bạn để tải lên các tập tin để bạn máy chủ. Yêu cầu POST có thể bị chặn theo một số cách. Hãy suy nghĩ về trình duyệt addons, proxy, Perl script. Dù chúng tôi có cố gắng thế nào đi chăng nữa, chúng tôi không thể ngăn một kẻ tấn công cố gắng tải lên một thứ gì đó mà anh ta không được phép. Vì vậy, tất cả các bảo mật của chúng tôi phải được thực hiện serverside.

Vấn đề đầu tiên là loại tệp. Trong kịch bản trên, kẻ tấn công có thể tải lên bất kỳ thứ gì anh ta muốn, ví dụ như một tập lệnh php và theo một liên kết trực tiếp để thực thi nó. Vì vậy, để ngăn chặn điều này, chúng tôi thực hiện Content-type xác minh:

<?php 
if($_FILES['image']['type'] != "image/png") { 
    echo "Only PNG images are allowed!"; 
    exit; 
} 

$uploaddir = 'uploads/'; 

$uploadfile = $uploaddir . basename($_FILES['image']['name']); 

if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadfile)) { 
    echo "Image succesfully uploaded."; 
} else { 
    echo "Image uploading failed."; 
} 
?> 

Unfortunetely này là không đủ. Như tôi đã đề cập trước đây, kẻ tấn công có toàn quyền kiểm soát yêu cầu. Không có gì ngăn cản anh ta/cô ấy sửa đổi các tiêu đề yêu cầu và chỉ cần thay đổi kiểu Nội dung thành "hình ảnh/png". Vì vậy, thay vì chỉ dựa vào tiêu đề Kiểu nội dung, tốt hơn hết là xác thực nội dung của tệp được tải lên. Đây là nơi thư viện GD php có ích. Sử dụng getimagesize(), chúng tôi sẽ xử lý hình ảnh bằng thư viện GD. Nếu đó không phải là hình ảnh, điều này sẽ không thành công và toàn bộ quá trình tải lên sẽ không thành công:

<?php 
$verifyimg = getimagesize($_FILES['image']['tmp_name']); 

if($verifyimg['mime'] != 'image/png') { 
    echo "Only PNG images are allowed!"; 
    exit; 
} 

$uploaddir = 'uploads/'; 

$uploadfile = $uploaddir . basename($_FILES['image']['name']); 

if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadfile)) { 
    echo "Image succesfully uploaded."; 
} else { 
    echo "Image uploading failed."; 
} 
?> 

Chúng tôi vẫn chưa có. Hầu hết các loại tệp hình ảnh đều cho phép thêm nhận xét văn bản vào chúng. Một lần nữa, không có gì ngăn cản kẻ tấn công thêm một số mã php làm bình luận. Thư viện GD sẽ đánh giá đây là một hình ảnh hoàn toàn hợp lệ. Trình thông dịch PHP sẽ hoàn toàn bỏ qua hình ảnh và chạy mã php trong nhận xét. Đúng là nó phụ thuộc vào cấu hình php mà phần mở rộng tệp được xử lý bởi trình thông dịch php và không, nhưng vì có nhiều nhà phát triển không có quyền kiểm soát cấu hình này do sử dụng VPS, chúng tôi không thể giả định trình thông dịch php sẽ không xử lý hình ảnh. Đây là lý do tại sao việc thêm một danh sách trắng mở rộng tập tin cũng không đủ an toàn.

Giải pháp cho việc này là lưu trữ hình ảnh ở vị trí mà kẻ tấn công không thể truy cập tệp trực tiếp.Đây có thể là bên ngoài của các tài liệu gốc hoặc trong một thư mục được bảo vệ bởi một tập tin .htaccess:

order deny,allow 
deny from all 
allow from 127.0.0.1 

Edit: Sau khi nói chuyện với một số lập trình viên PHP khác, tôi đánh giá cao đề nghị sử dụng một thư mục bên ngoài của các tài liệu gốc, vì htaccess không phải lúc nào cũng đáng tin cậy.

Chúng tôi vẫn cần người dùng hoặc bất kỳ khách truy cập nào khác có thể xem hình ảnh. Vì vậy, chúng tôi sẽ sử dụng php để lấy lại hình ảnh cho họ:

<?php 
$uploaddir = 'uploads/'; 
$name = $_GET['name']; // Assuming the file name is in the URL for this example 
readfile($uploaddir.$name); 
?> 

vấn đề thứ hai: địa phương tấn công tập tin bao gồm
Mặc dù kịch bản của chúng tôi là an toàn hợp lý bởi bây giờ, chúng ta không thể giả định máy chủ không bị các lỗ hổng khác. Lỗ hổng bảo mật phổ biến được gọi là Bao gồm tệp cục bộ. Để giải thích điều này, tôi cần phải thêm mã ví dụ:

<?php 
if(isset($_COOKIE['lang'])) { 
    $lang = $_COOKIE['lang']; 
} elseif (isset($_GET['lang'])) { 
    $lang = $_GET['lang']; 
} else { 
    $lang = 'english'; 
} 

include("language/$lang.php"); 
?> 

Trong ví dụ này, chúng ta đang nói về một trang web đa ngôn ngữ. Ngôn ngữ của trang web không phải là thứ được coi là thông tin "có nguy cơ cao". Chúng tôi cố gắng thu hút khách truy cập thích ngôn ngữ thông qua cookie hoặc yêu cầu GET và bao gồm tệp được yêu cầu dựa trên đó. Bây giờ considder gì sẽ xảy ra khi những kẻ tấn công vào url sau:

www.example.com/index.php?lang=../uploads/my_evil_image.jpg

PHP sẽ bao gồm các tập tin được tải lên bởi những kẻ tấn công bỏ qua thực tế là (s) anh ta không thể truy cập trực tiếp vào tập tin và chúng ta quay trở lại hình vuông.

Giải pháp cho vấn đề này là đảm bảo người dùng không biết tên tệp trên máy chủ. Thay vào đó, chúng tôi sẽ thay đổi tên tập tin và thậm chí cả phần mở rộng sử dụng một cơ sở dữ liệu để theo dõi nó:

CREATE TABLE `uploads` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `name` VARCHAR(64) NOT NULL, 
    `original_name` VARCHAR(64) NOT NULL, 
    `mime_type` VARCHAR(20) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 


<?php 

if(!empty($_POST['upload']) && !empty($_FILES['image']) && $_FILES['image']['error'] == 0)) { 

    $uploaddir = 'uploads/'; 

    /* Generates random filename and extension */ 
    function tempnam_sfx($path, $suffix){ 
     do { 
      $file = $path."/".mt_rand().$suffix; 
      $fp = @fopen($file, 'x'); 
     } 
     while(!$fp); 

     fclose($fp); 
     return $file; 
    } 

    /* Process image with GD library */ 
    $verifyimg = getimagesize($_FILES['image']['tmp_name']); 

    /* Make sure the MIME type is an image */ 
    $pattern = "#^(image/)[^\s\n<]+$#i"; 

    if(!preg_match($pattern, $verifyimg['mime']){ 
     die("Only image files are allowed!"); 
    } 

    /* Rename both the image and the extension */ 
    $uploadfile = tempnam_sfx($uploaddir, ".tmp"); 

    /* Upload the file to a secure directory with the new name and extension */ 
    if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadfile)) { 

     /* Setup a database connection with PDO */ 
     $dbhost = "localhost"; 
     $dbuser = ""; 
     $dbpass = ""; 
     $dbname = ""; 

     // Set DSN 
     $dsn = 'mysql:host='.$dbhost.';dbname='.$dbname; 

     // Set options 
     $options = array(
      PDO::ATTR_PERSISTENT => true, 
      PDO::ATTR_ERRMODE  => PDO::ERRMODE_EXCEPTION 
     ); 

     try { 
      $db = new PDO($dsn, $dbuser, $dbpass, $options); 
     } 
     catch(PDOException $e){ 
      die("Error!: " . $e->getMessage()); 
     } 

     /* Setup query */ 
     $query = 'INSERT INTO uploads (name, original_name, mime_type) VALUES (:name, :oriname, :mime)'; 

     /* Prepare query */ 
     $db->prepare($query); 

     /* Bind parameters */ 
     $db->bindParam(':name', basename($uploadfile)); 
     $db->bindParam(':oriname', basename($_FILES['image']['name'])); 
     $db->bindParam(':mime', $_FILES['image']['type']); 

     /* Execute query */ 
     try { 
      $db->execute(); 
     } 
     catch(PDOException $e){ 
      // Remove the uploaded file 
      unlink($uploadfile); 

      die("Error!: " . $e->getMessage()); 
     } 
    } else { 
     die("Image upload failed!"); 
    } 
} 
?> 

Vì vậy, bây giờ chúng tôi đã thực hiện như sau:

  • Chúng tôi đã tạo một nơi an toàn để lưu hình ảnh
  • Chúng tôi đã xử lý hình ảnh với thư viện GD
  • Chúng tôi đã kiểm tra các loại hình ảnh MIME
  • Chúng tôi đã đổi tên thành tên file và thay đổi phần mở rộng
  • Chúng tôi đã lưu cả tên tập tin mới và độc đáo trong cơ sở dữ liệu của chúng tôi
  • Chúng tôi cũng đã lưu MIME nhập vào cơ sở dữ liệu của chúng tôi

Chúng tôi vẫn cần có khả năng hiển thị hình ảnh cho khách truy cập. Chúng tôi chỉ cần sử dụng cột id của cơ sở dữ liệu của chúng tôi để thực hiện việc này:

<?php 

$uploaddir = 'uploads/'; 
$id = 1; 

/* Setup a database connection with PDO */ 
$dbhost = "localhost"; 
$dbuser = ""; 
$dbpass = ""; 
$dbname = ""; 

// Set DSN 
$dsn = 'mysql:host='.$dbhost.';dbname='.$dbname; 

// Set options 
$options = array(
    PDO::ATTR_PERSISTENT => true, 
    PDO::ATTR_ERRMODE  => PDO::ERRMODE_EXCEPTION 
); 

try { 
    $db = new PDO($dsn, $dbuser, $dbpass, $options); 
} 
catch(PDOException $e){ 
    die("Error!: " . $e->getMessage()); 
} 

/* Setup query */ 
$query = 'SELECT name, original_name, mime_type FROM uploads WHERE id=:id'; 

/* Prepare query */ 
$db->prepare($query); 

/* Bind parameters */ 
$db->bindParam(':id', $id); 

/* Execute query */ 
try { 
    $db->execute(); 
    $result = $db->fetch(PDO::FETCH_ASSOC); 
} 
catch(PDOException $e){ 
    die("Error!: " . $e->getMessage()); 
} 

/* Get the original filename */ 
$newfile = $result['original_name']; 

/* Send headers and file to visitor */ 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename='.basename($newfile)); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate'); 
header('Pragma: public'); 
header('Content-Length: ' . filesize($uploaddir.$result['name'])); 
header("Content-Type: " . $result['mime_type']); 
readfile($uploaddir.$result['name']); 
?> 

Nhờ tập lệnh này, khách truy cập sẽ có thể xem hình ảnh hoặc tải xuống với tên tệp ban đầu. Tuy nhiên, anh ta không thể truy cập tập tin trên máy chủ của bạn và cũng sẽ không thể đánh lừa máy chủ của bạn để truy cập vào tập tin cho anh ta/cô ấy như (s) anh ta không có cách nào để biết tập tin đó là .(S) ông không thể brute lực lượng thư mục tải lên của bạn, hoặc vì nó chỉ đơn giản là không cho phép bất cứ ai truy cập vào thư mục ngoại trừ chính máy chủ.

Và điều đó kết thúc kịch bản tải lên hình ảnh an toàn của tôi.

Tôi muốn thêm rằng tôi đã không bao gồm kích thước tệp tối đa vào tập lệnh này, nhưng bạn có thể dễ dàng tự làm điều đó.

ImageUpload Lớp
Do nhu cầu cao của kịch bản này, tôi đã ghi chép lại một lớp ImageUpload rằng nên làm cho nó dễ dàng hơn nhiều cho tất cả các bạn để xử lý một cách an toàn các hình ảnh được tải lên bởi người truy cập website của bạn. Lớp học có thể xử lý cả hai tệp đơn và nhiều lần cùng một lúc và cung cấp cho bạn các tính năng bổ sung như hiển thị, tải xuống và xóa hình ảnh.

Kể từ mã chỉ đơn giản là để lớn để đăng bài viết, bạn có thể tải về các lớp từ MEGA ở đây:

Download ImageUpload Class

Chỉ cần đọc README.txt và làm theo hướng dẫn.

Đi Open Source
Dự án an toàn lớp hình ảnh bây giờ cũng có sẵn trong hồ sơ của Github của tôi là. Điều này để những người khác (bạn?) Có thể đóng góp cho dự án và biến nó trở thành một thư viện tuyệt vời cho mọi người.

+4

icecub rất tốt đẹp này. Cũng yêu cả ảnh tiểu sử. Thx giúp ngày hôm trước. – Drew

+3

Hàm 'getimagesize()' nói rõ rằng bạn không nên sử dụng hàm này để xác nhận nếu một hình ảnh là một hình ảnh. 'Không sử dụng getimagesize() để kiểm tra xem một tệp đã cho là một hình ảnh hợp lệ hay không. Sử dụng giải pháp được xây dựng có mục đích chẳng hạn như phần mở rộng Fileinfo thay thế.' http://php.net/manual/en/function.getimagesize.php –

+0

Điều này có hoạt động với nhiều video tải lên không? Ví dụ: tôi tải lên 3 hình ảnh trong một biểu mẫu gửi? – Lachie

1

Vâng, để tải tệp lên trong PHP quá dễ dàng và bảo mật. tôi khuyên về Lear:

  • pathinfo - Trả thông tin về một đường dẫn tập tin
  • move_uploaded_file - Di chuyển một tập tin được tải lên một vị trí mới
  • copy - Bản sao tập tin
  • finfo_open - Tạo một tài nguyên fileInfo mới

Để tải lên tệp bằng PHP, bạn có hai phương pháp, PUT và POST (có thể hơn ..). Để sử dụng phương thức POST với HTML cần cho phép enctype vào mẫu như thế này:

<form action="" method="post" enctype="multipart/form-data"> 
    <input type="file" name="file"> 
    <input type="submit" value="Upload"> 
</form> 

Sau đó, trong bạn PHP bạn cần bắt bạn tải lên tập tin với $_FILES như thế này:

$_FILES['file'] 

Sau đó, bạn cần phải di chuyển từ tạm thời ("tải lên") với move_uploaded_file:

if (move_uploaded_file($_FILES['file']['tmp_name'], YOU_PATH)) { 
    // ... 
} 

Và sau khi tải lên tệp, bạn cần tiện ích mở rộng kiểm tra và cách tốt nhất và tốt hơn là sử dụng pathinfo như thế này:

$extension = pathinfo($_FILES['file']['tmp_name'],PATHINFO_EXTENSION); 

Nhưng phần mở rộng không là an toàn bởi vì bạn có thể tải tập tin với phần mở rộng .jpg nhưng với Mimetype text/php và đây là một backdoor. Vì vậy, tôi khuyên bạn nên kiểm tra Mimetype thực với finfo_open như thế này:

$mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $_FILES['file']['tmp_name']); 

Và, không sử dụng $_FILES['file']['type'] bởi vì đôi khi và tùy thuộc trình duyệt và hệ điều hành client, bạn có thể nhận application/octet-stream, và Mimetype này không là một số thực sự là mimetype của bạn đã tải lên tệp.

Tôi nghĩ với điều này, bạn có thể tải tệp lên bằng bảo mật.

Xin lỗi tiếng anh của tôi, bye!

+0

Xin chào, cảm ơn bạn đã trả lời. Tuy nhiên, tôi không nghĩ rằng nó hoàn toàn trả lời cho câu hỏi của tôi. Tôi có kịch bản bao gồm tất cả các chức năng được đề cập của bạn. Tuy nhiên, nó không làm cho kịch bản hoàn toàn an toàn vì chúng ta có thể đọc ở đây http://security.stackexchange.com/questions/32852/risks-of-a-php-image-upload-form. Tôi đã hy vọng rằng ai đó sẽ cung cấp cho (không cần phải viết mã, có thể ai đó đã có nó) tất cả các chức năng được đề cập trên câu trả lời trước đó, mà sẽ làm cho kịch bản tải lên hình ảnh an toàn nhất có thể. Tuy nhiên, cảm ơn một lần nữa vì nỗ lực của bạn để trả lời câu hỏi này. – Simon

+0

@Simon Trong phần hình ảnh, có rất nhiều thứ bạn cần cân nhắc khi lưu trữ và hiển thị nó. Tôi hy vọng trên nền tảng này sẽ có rất nhiều người giúp bạn lưu trữ một phần. Nhưng liên quan đến việc hiển thị một phần, tôi sẽ khuyên bạn nên xem qua http://php.net/manual/en/book.imagick.php – Lokesh

Các vấn đề liên quan