PHP防盜鏈
來源:互聯網
上載者:User
我用的apache 2, php 4.3
有下面一段請求:
GET /include/http/download.php?name=setup.exe HTTP/1.1
Host: localhost
Accept: */*
User-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)
Range: bytes=19434798-
Pragma: no-cache
Cache-Control: no-cache
Connection: close
這樣一段請求,注意:
bytes=19434798-
而我的download.php只有10000位元組大,裡面的代碼作了這樣的工作:
根據客戶url傳來的內容和http頭中傳來的開始位置,在伺服器端迴圈讀取相應的檔案,並且echo到用戶端。目的是徹底實現“防盜鏈”,並實現下載計數。因為單純redirect到真實url根本起不到防盜作用。
但是只要request的Range欄位指定的起始下載位置比download.php自身的大小還要大,根本就沒有來得及起動php解析器解析並執行download.php,直接在apache層就給回絕了。
問題:
1、有沒有辦法得到http要求標頭的range欄位?如果有的話,我不知道是否能夠避免apache直接就回絕range“不合理”的請求。
2、如果我這樣的想法不可以實現,實現作防盜鏈並且能夠支援多線程下載的辦法是什嗎?
謝謝!
---------------------------------------------------------------
<?php
$dir=$HTTP_GET_VARS["dir"]; //.......取得上個頁面傳遞來的路徑
$file=$HTTP_GET_VARS["file"]; //.......取得傳遞來的檔案名稱
$url=parse_url($HTTP_REFERER); /*......取得前一頁面的URL地址,並將其放入一個數組中*/
if($url[host]!=$HTTP_HOST){echo "要下載本軟體請到<a href=http://www.df365.org>東方小屋</a>";exit;} /*檢查來源網站是不是自己的網站,如果不是,返回“要下載本……”*/
if(empty($dir))$dir="/"; //......如果路徑名為空白,則為指定根目錄
if(empty($file)){echo "未指定要下載的檔案!";exit;} /*如果檔案名稱為空白,返回“未指定……”*/
$rootdir="檔案存放的根目錄";//......你的下載路徑根目錄
$realurl=$rootdir.$dir; //.......取得你的下載目錄
chdir($realurl); //......將目前的目錄轉到下載目錄中
if(!file_exists($file)){echo "對不起,此連結已經失效,請在下載頁面上向我們報告,謝謝!";exit;} //......測試檔案是否存在
$filename=$file;
// 傳送檔案頭資訊
header("Cache-control: private"); // fix for IE
header("Content-Type: application/octet-stream");
header("Content-Length: ".filesize($filename));
header("Content-Disposition: attachment; filename=$filename");
$fp = fopen($filename, 'r'); // 以讀取方式開啟指定檔案
fpassthru($fp); // ** CORRECT ** 以二進位方式讀取檔案
fclose($fp); // 關閉檔案
?>
---------------------------------------------------------------
http://www.phpx.com/happy/thr65431.html這篇文章。
針對網頁上做防盜鏈沒什麼好辦法。
最好是在伺服器端加強。
---------------------------------------------------------------
我試過還不錯
//以下內容為程式碼:
<?php
require_once ("./inc/global.php");
require_once ("./inc/mysql4.php");
$id = $_GET['id'];
$db = open_db();
if ($result = $db->sql_query("SELECT * FROM ring WHERE id = '$id'")) {
$row = $db->sql_fetchrow($result);
$file = $row['file'];
$size = $row['size'];
send_midi($id, $file, $size);
} else {
require_once ("function.php");
err404();
}
function send_midi($id, $file, $size) {
header ("Content-type: audio/midi");
header ("Content-length: $size");
header ("Content-Disposition: attachment; filename=/"".$id.".mid/"");
echo ($file);
}
?>
這樣可以通過判斷HTTP_REFERER或者用會員認證的方式來提供下載,因為永遠看不到真實路徑。不過缺點是影響效能,而且似乎不支援續傳(未驗證)。實際示範在http://wap.yeesee.net/browser.php,點開一個midi後,裡面會出現,而你無論用什麼方法,都看不到實際地址。(本例中檔案儲存體在資料庫中,實際使用時候你可以不這麼做,readfile就行)