2016-12-07 52 views
3

我想使PDF可下載,不能通過url直接訪問。PHP:readfile()使用&時出現錯誤下載(&符號)

這是鏈接會是什麼樣子

<a href="getFile.php?file=myfile.pdf" >Myfile</a> 

,這是getFile.php

<?php 

    $file=$_GET['file']; 

    // Check if file really exists: 
    $files = array_diff(scandir('/www/secretPlace/'), array('.', '..')); 
    $show = (in_array($file,$files)) ? true : false; 
    if(!$show) exit(); 

    header('Content-Type: application/pdf'); 
    header('Content-Disposition: attachment; filename="' . $file . '"'); 
    readfile('/www/secretPlace/' . $file); 

這工作得很好,只要PDF名稱不包括&符號。 如果我嘗試

<a href="getFile.php?file=myfile & other stuff.pdf" >My Special File</a> 

我將能夠下載與名稱的文件,但我不能用pdf閱讀器打開它。所有程序都告訴我該文件已損壞。我如何獲得帶有名稱中帶有&符號的readfile的pdf文件?

+5

從來沒有過的用戶輸入的功能說明;如果你這樣做,用戶可以從你的服務器下載任何文件; – itzmukeshy7

+0

@ itzmukeshy7我添加了一個檢查,如果該文件實際上在目錄中。你認爲現在保存嗎?否則,我正在考慮使用http://stackoverflow.com/a/4205278/2311074。 – Adam

+0

不需要添加'foreach'循環,只需使用'in_array()'來檢查; – itzmukeshy7

回答

2

您的代碼易受路徑遍歷攻擊。我強烈建議你明確告訴用戶可以下載哪些文件。

您的問題(更新),

我建議您存儲文件名(編碼時並不需要)在數據庫中,然後每一行會有一個單獨的ID。您可以創建一個頁面,假設/download/1234ID 1234,因此您可以自動知道它屬於哪個文件,而不必混淆破壞URI字符串的特殊字符。可以在.htaccess,/download/[1-9][0-9]*中配置URL結構,指向您在問題中包含的PHP頁面,您應該在這裏處理所有這些問題。然後,您將從數據庫中獲取文件名,執行​​3210檢查以查看它是否存在,並使用Content-Disposition開始用戶下載。

如果你不喜歡的數據庫解決方案,您需要在URI字符串(尤其是&正如你所提到的)特殊字符進行編碼,或者編寫手工解析URI字符串的函數,而不是依賴於$_GET,這在渲染時將文本拆分爲&=

要在安全方面的擴展問題:

我可以提供文件名的此成真的話,即使他們不應該匹配。

if($pdf == $file) $show = true;    

如果使用三個等號,它會更好,但仍可能容易受到C空字節注入的影響。所以在這裏建議,一如既往,是白名單,而不是黑名單(在這種情況下..

+0

你是否建議我爲每個pdf製作一個頁面?因爲我正在尋找一個動態解決方案。我還爲我的** getFile.php **添加了一個檢查,以確保該文件實際存在於文件夾中(僅在我看到您的答案前1秒),所以我認爲它不容易受到** Path Traversal ** , 對? – Adam

+0

這是一個足夠動態的解決方案,如果您以正確的方式使用'.htaccess'來完成。您必須製作一個PHP頁面。 –

+0

它仍然容易受到特定的注射(CR,LF,空字節)。 (作爲一個建議,你永遠不會黑名單不好的輸入,你總是白名單好)。如果您想要提供特定的下載目錄,只需使用'glob'讀取文件名並將其列入白名單。 –

1

它沒有工作投入使用

<a href="getFile.php?file=myfile & other stuff.pdf" >My Special File</a> 

時,因爲那時

$file=$_GET['file']; 

僅具有值爲myfile。人們需要這樣的URL進行解碼:

<a href="getFile.php?file=<?php echo urlencode('myfile & other stuff.pdf'); ?>" >My Special File</a> 

安全白名單的方式可以由可能更安全的方法來代替在https://stackoverflow.com/a/4205278/2311074

相關問題