在網上看了數篇文章,都是說可以用來控制檔案下載的許可權。
其原理都是說訪問download.php時驗證許可權,如果通過則header("X-Accel-Redirect: 目標檔案")。
不過我有個疑問,要是我知道目標檔案的真實檔案名稱和存放路徑之後直接存取,那不是繞過了X-Accel-Redirect了?
舉個例子:
假設目標檔案實際存放在 http://www.1.com/download/123.xls
而在網站頁面上有下載連結 http://www.1.com/download.php?file=xxxx
那麼通過該連結可以實現許可權控制,但是如果我直接輸入http://www.1.com/download/123.xls進行訪問呢?不是繞過了許可權控制了嗎?
回複討論(解決方案)
在web應用中,常常會有檔案需要下載。如果這些檔案是非常私密的,直接用web伺服器下載,就不能檢查檔案的下載許可權。以往遇到這種需要許可權的情況,都 是用程式語言判定許可權後,使用程式語言來讀取檔案並輸出,這樣就能解決許可權問題。但是使用程式語言來讀取檔案又帶來了效率上的問題,如果檔案體積比較大或 者下載並發數比較大,伺服器很快就不堪重負。
基於這種情況,web伺服器軟體提供了相應的解決辦法:使用一個response header來控制下載。目前squid、apache、lighttpd、nginx等http server都有支援這種方式,但是他們的response header的名字都不一樣:
nginx: X-Accel-Redirect
squid: X-Accelerator-Vary
apache: X-Sendfile
lighttpd: X-Sendfile/X-LIGHTTPD-send-file
用response header控制下載的原理都大同小異:
當用戶端發起請求下載某個檔案時,因為並沒有X-Accel-Redirect頭,web伺服器並不會立刻就把檔案輸出給用戶端;而是將這個請求交給後端 的程式語言,程式語言驗證認為該用戶端可以下載這個檔案,就寫出相應的X-Accel-Redirect頭並結束處理;X-Accel-Redirect 頭返回時經過前端的web伺服器,web伺服器檢查到這個頭之後,才把檔案輸出到用戶端。
那麼,如果用戶端偽造一個X-Accel-Redirect頭來讀取呢?當然也是不能下載的,因為web伺服器只認識後端發來的X-Accel-Redirect頭,用戶端發來的不算。
於是下面就用nginx來實現上述的這個流程:
1、改變目錄許可權,用戶端發起請求時,將這個目錄的請求都交給後端
location /mp3/ {
alias /data/html/mp3/;
internal;
error_page 403 =200 @backend;
}
location @backend {
proxy_pass http://www.sudone.com;
}
這樣,使用者訪問如http://www.sudone.com/mp3/1.mp3這樣的地址時,將不能下載檔案,nginx會把請求交給後端伺服器。
2、在後端伺服器配置一個rewrite
rewrite "^/mp3/(.*)\.mp3$" /read_file.php?id=$1 last;
這個rewrite的目的是把請求http://www.sudone.com/mp3/1.mp3指向到一個php程式語言上,由程式語言處理。
3、寫一個php程式判斷許可權
如限定時間內(19點到23點)可以下載檔案:
$hour=getdate()[hours];
if ($hour>=19 && $hour<=23)
{
header("Content-Type: application/octet-stream");
header("X-Accel-Redirect: /mp3/".$id.".mp3");
}
?>
每天晚上的19點到23點訪問該地址都會輸出X-Accel-Redirect頭,內容是檔案地址。輸出X-Accel-Redirect頭之後,檔案才能被下載,否則用戶端什麼都得不到。所以就實現了晚上19點到23點才能下載到檔案,其他時間段就不能了。
這樣,配置就完成了。
自己也試著配置了一把,PHP是把請求重新轉寄了,只是到最後一步的時候伺服器總報404錯誤,一直找不出原因。不知道是不是跟版本有關係,自己裝的nginx的version資訊又被我改了所以查不到版本號碼。
1樓不厚道啊,我就是看文章不明白才來這裡問的,你帖的這篇文章我看過幾次了,由於對apache不夠熟悉沒能完全看明白。
望樓下高手解答
你有測試過嗎, discuz x2支援這個功能, 改天我先測試下看看
1樓不厚道啊,我就是看文章不明白才來這裡問的,你帖的這篇文章我看過幾次了,由於對apache不夠熟悉沒能完全看明白。
望樓下高手解答
這種情況下,你要下載的檔案肯定是放在web根目錄以外,也就是http直接存取是訪問不了的。
比如,http://www.123.com/ 指向目錄:/home/httpd/html,下載的檔案123.exe在伺服器的實際路徑可能就是/home/soft/123.exe,這樣nginx等伺服器軟體可以訪問,web使用者卻無法通過http方式來訪問