使用 Nginx 的 X-Sendfile 機制控制檔案訪問許可權(php版)
BBS或者網站經常會有隻有你有許可權才能看到這個頁面,或者下載這個資源,日前探訪了nginx伺服器怎麼實現這個檔案控制的,用到了x-sendfile。
一、什麼是 X-Sendfile?
X-Sendfile 是一種將檔案下載請求由後端應用轉交給前端 web 伺服器處理的機制,它可以消除後端程式既要讀檔案又要處理髮送的壓力,從而顯著提高伺服器效率,特別是處理大檔案下載的情形下。
X-Sendfile 通過一個特定的 HTTP header 來實現:在 X-Sendfile 頭中指定一個檔案的地址來通告前端 web 伺服器。當 web 伺服器檢測到後端傳送的這個 header 後,它將忽略後端的其他輸出,而使用自身的元件(包括 快取頭 和 斷點重連 等優化)機制將檔案傳送給使用者。
不過,在使用 X-Sendfile 之前,我們必須明白這並不是一個標準特性,在預設情況下它是被大多數 web 伺服器禁用的。而不同的 web 伺服器的實現也不一樣,包括規定了不同的 X-Sendfile 頭格式。如果配置失當,使用者可能下載到 0 位元組的檔案。
使用 X-Sendfile 將允許下載非 web 目錄中的檔案(例如/root/),即使檔案在 .htaccess 保護下禁止訪問,也會被下載。
SENDFILE 頭 | 使用的 WEB 伺服器 |
---|---|
X-Sendfile | Apache, Lighttpd v1.5, Cherokee |
X-LIGHTTPD-send-file | Lighttpd v1.4 |
X-Accel-Redirect | Nginx, Cherokee |
使用 X-SendFile 的缺點是你失去了對檔案傳輸機制的控制。例如如果你希望在完成檔案下載後執行某些操作,比如只允許使用者下載檔案一次,這個 X-Sendfile 是沒法做到的,因為後臺的 php 指令碼並不知道下載是否成功。
二、NGINX怎樣使用?
Nginx 預設支援該特性,不需要載入額外的模組。只是實現有些不同,需要傳送的 HTTP 頭為 X-Accel-Redirect。另外,需要在配置檔案中做以下設定
location /game/ {
internal;
alias /data/app/php/open.game.liebao.cn/default/game/; //檔案可以放到別的目錄
error_page 404 =200 @backend; // 如果訪問出現404轉發到後臺伺服器
}
location @backend {
#proxy_pass http://test.open.game.cn; // 可以客戶端發起請求時,將這個目錄的請求代理到其他機器
rewrite ^/game/(.*)$ /read_file.php?fn=$1 last; // 客戶端發起請求時,rewritet跳轉到後臺程式
}
internal 表示這個路徑只能在 Nginx 內部訪問,不能用瀏覽器直接訪問防止未授權的下載。
三、php程式怎樣使用?
<?php$pay = 2;
$path = $_GET["fn"]; //獲取使用者訪問的url引數
if ($pay>1) //付過錢的 加上X-Accel-Redirect的頭,就能訪問到,否則無法訪問
{
// header("Content-Type: application/octet-stream"); //檔案下載時候用到
header("X-Accel-Redirect: /game/".$path);
}
?> 如果加上了加上X-Accel-Redirect的頭,這樣使用者就會下載到 /game 這個路徑下的檔案。我們的檔案許可權控制就實現了。