2010-08-12 70 views
8

我在Windows平臺上使用GoDaddy虛擬主機計劃。這不是我的選擇 - 它與使用ASP.NET的實際站點的不同部分有關(也不是我的選擇)。限制文件訪問 - 只能通過PHP讀取

我有一個SQL數據庫與一堆條目與一些不敏感的客戶信息。這裏的主鍵是一個AutoIncrement整數,並且我有一系列與這些整數相匹配的PDF文件(例如555.pdf,7891.pdf等)。

我的目標是限制直接訪問這些文件,我希望用戶必須先通過搜索和登錄過程(PHP)。最初我打算把這些文件放在PUBLIC_HTML文件夾的上面,但是GoDaddy拒絕給我沒有專用服務器的root訪問權限(每月20美元)。

我接下來看到的是HTACCESS。我打算通過只允許訪問服務器的IP地址(或localhost/127.0.0.1)來限制對文件的訪問。不幸的是,這不起作用,因爲GoDaddy不在Windows服務器上運行Apache。

我可以將這些文件放入數據庫中的BLOB中,但是當我需要快速使用它們時(這種方法遇到了一些麻煩),這會變得非常混亂。

任何建議只限於一個PHP腳本(readfile())文件的訪問?

+0

這將取決於他們正在使用的網絡服務器(IIS,假設)。也許你應該用IIS標記這個。 – Artefacto 2010-08-12 23:24:02

回答

5

因爲你不能把文件的任何地方,但在你的public_html目錄,你必須「通過隱藏的安全」去的恐懼/憎恨方法

  1. 創建一個隨機命名的子目錄將文件存儲在:public_html/RANDOMGARBAGE

  2. 確保該目錄不可瀏覽。禁用目錄瀏覽(如果可以的話),並在其中放置一個默認文檔(index.html?),所以即使瀏覽了,也不會獲得目錄列表。

  3. 不要用可猜測的名稱存儲您的文件。而不是使用數據庫ID存儲它們,而是使用salted +哈希名稱來存儲它們:$crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');(當然,如果需要,可以使其更復雜)。將原始文件名存儲在數據庫中。所以,你最終的東西,如:

    public_html/RANDOMGARBAGE/5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 public_html/RANDOMGARBAGE/7ec1f0eb9119d48eb6a3176ca47380c6496304c8

  4. 通過PHP腳本即成了文件 - 從來沒有鏈接到散列文件名直接

    下載

然後做:

<?php 

    $fileID = (int)$_GET['fileID']; 

    $crypted_file = sha1($fileID . 'some hard-to-guess salt text'); 

    $full_path = 'public_html/RANDOMGARBAGE/' . $crypted_file; 
    if (is_readable($full_path)) { 
     if(user_is_allowed_to_see_this_file()) { 
      /// send file to user with readfile() 
      header("Content-disposition: attachment; filename=$ORIGINAL_FILENAME"); 
      readfile($full_path); 
     } else { 
      die("Permission denied"); 
     } 
    } else { 
     /// handle problems here 
     die("Uh-oh. Can't find/read file"); 
    } 

這樣,用戶將永遠不會看到你的「s00per seekrit」文件名是什麼,他們就會看到他們的瀏覽器中點擊...php?fileID=37,並開始下載的secret file.pdf

在此之上,你可以偶爾重命名的特殊子目錄定期更新到別的東西,以及更改鹽文本(然後需要使用新的sha1值更新所有哈希文件名)。

0

您可以簡單地隱藏它們。它的安全性至關重要,但如果您不能將它們放在網絡根目錄下,或者找到一種方法告訴服務器不要直接提供服務,它聽起來像是您的最佳選擇。

所以堅持他們在一些隨機命名的目錄:

asd8b8asd8327bh/123.pdf 
asd8b8asd8327bh/124.pdf 
asd8b8asd8327bh/125.pdf 
... 

然後自己寫一個小PHP腳本,將發送適當的報頭,並通過傳遞文件內容。

例如:

<?PHP 
//pdf.php 
$id = $_GET['id']; 

//make sure nobody is doing anything sneaky. is_numeric() might do the trick if the IDs are always integers. 
if (!some_validation_passes($id)){ 
    die(); 
} 
<?php 

header('Content-type: application/pdf'); 
header('Content-Disposition: attachment; filename="'.$id.'.pdf"'); 
readfile('asd8b8asd8327bh'.$id.'pdf'); 

現在,上面的不僅僅是服務於文件直接(還)真的沒有更好的,因爲人們仍然可以增加在查詢字符串的ID參數。

但你應該能夠弄清楚如何輕鬆處理授權。

+0

這是通過默默無聞的安全。換句話說,不安全。 – Borealid 2010-08-12 23:31:29

+0

@Borealid你說,就好像我沒有明確限定我的答案在第一行。不要通過默默無聞的討論安全問題,而是「這是軟件,換句話說,不安全」。或者「這是一個密碼系統,因此不安全」。事實上,現在我想到了,我的解決方案與強密碼一樣安全,假設沒有無關的漏洞讓攻擊者列出目錄。 – timdev 2010-08-12 23:44:49

0

通過chmod使文件夾無法訪問。 PHP仍然能夠包含/要求服務器上的任何內容,但用戶將無法導航到有史以來的文件。

例如: 這設置爲770,IE用戶和組可以讀/寫/執行,其他什麼也不能做。

+0

這個答案是錯誤的。除了SuExec/CGI配置,PHP使用Web服務器的權限。如果該文件無法訪問Web服務器,則PHP也無法訪問該文件。 – Borealid 2010-08-12 23:32:32

+0

我有一個文件夾設置爲770,我可以包含,但無法直接在瀏覽器中導航。 – Robert 2010-08-12 23:37:02

+0

另外我想你誤解了,網絡服務器仍然有權限,用戶和組在770有權限,其他人沒有。因此,這使得PHP可以完全訪問文件,Web瀏覽器將不會得到任何東西。 – Robert 2010-08-12 23:42:53

1

因爲PHP使用網絡服務器用戶的權限,有沒有辦法來限制訪問的文件,而無需之一:

  • 將它們放在DOCROOT
  • 外部更改Web服務器配置爲禁止訪問這些文件
  • 更改文件,因此這將是由Web服務器進行解釋,從而隱藏其內容

把它們放在一個數據庫算作outsi DOCROOT。對於第三種選擇,您可以製作PDF文件,但說實話,這會非常複雜。

我建議您聯繫GoDaddy,看看他們是否有一些方法來配置每個目錄的文件權限。

+0

聰明。假設OP對服務器無能爲力,我喜歡你的第三種選擇,再加上我概述的基本代碼。 – timdev 2010-08-12 23:46:23