大家好:
因為不想要讓使用者知道檔案直接的路徑,所以用get的方式從b.php直接下載檔案
首先是用確認UID的session有無值,沒值就轉址,有值再比對使用者ip對不對,如果使用者把連結傳給別人,ip不對也會轉址。
現在遇到問題是使用者已經login,UID有值,所以可以直接下載檔案,但是如果使用者把a.php的連結貼到另一個瀏覽器,UID應該是沒值就不能下載,直接轉址。
測試好像是header($reff);的關係,如果單純打echo文字的話,使用者貼在另一個瀏覽器是可以轉址的,但用改header($reff)使用者的瀏覽器(沒做登入應該UID會沒有值)馬上可以看到直接路徑..
想請問是甚麼問題呢?
謝謝
a.php
<a href="./b.php?type=bclass&files=20201106.jpg&id=192.168.1.1" target="_blank" download="2020/11/06 16:33">可點檔案確認</a>
b.php
<?php
session_start();
if(empty($_SESSION['UID'])){
header("Location:login.php");
}?>
<?php
function get_ip(){
if (!empty($_SERVER["HTTP_CLIENT_IP"])){
$ip = $_SERVER["HTTP_CLIENT_IP"];
}elseif(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}else{
$ip = $_SERVER["REMOTE_ADDR"];
}
return $ip;
}
?>
<?php
try{
$filename=$_GET['files'];
$ipname=$_GET['id'];
$filetype=$_GET['type'];
$sqlr="SELECT * FROM feed where jpgdata=:pdfdatan and ip=:ipid";
$reff="Location: ./uploa/".$filename;
if(get_ip()==$ipname){
$conn=new PDO("mysql:host=$hostdb;dbname=$namedb",$userdb,$passdb);
//echo '資料庫伺服器連線及資料庫開啟成功';
$conn->exec("SET CHARACTER SET utf8");
$sql=$sqlr;
$result = $conn->prepare($sql);
$result->execute(array("pdfdatan"=>$filename,"ipid"=>$ipname));
if($result && ($result->rowCount()>0)){
header($reff);
}
else{
echo "非上傳者";
}
}
else{
header('Location:https://www.yahoo.com.tw');
}
}
請注意一下瀏覽器的特性。並確定session的繼承性為何。
一般來說,chroom。另開分頁會重置session id(window open除外)
但ie瀏覽器另開分頁是會被繼承session id。
如果你的session是採用cookie的記錄方式的話。
則瀏覽器都會被繼承居多。(可能吧)
所以在研究你這個問題之前。你得先確定好你的session的情況。再來看是否有問題。
另。跑header並不一定會中斷程式。如果有多個header要特別小心。
一般來說。會盡量只安排一個header。然後用變數來對應url處理。
這樣可以防止週期生命的問題。
千萬不要賭header會轉頁以下程式不會跑的想法。
最後,這個程式碼有非常多需要改善的空間。等我有空閒再看看。
謝謝您提醒..目前都用session處理
但發現html的donwload 好像不能支援對手機跟一些瀏覽器(IE)
測過一些瀏覽器跟手機瀏覽器目前可以直接下載 不知道還有沒有其他漏洞..
有做以下修正,再麻煩您指導 謝謝您
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename='. $filen);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($reff);
可以試試加上
header("Content-Length: " .(string)(filesize($filen)) );
然後這一段
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
基本上我會建議拿掉。這段在一般處理json或是文件檔很好用。
不過二進位檔就容易有問題。
大多數來說比較容易碰到記憶體的問題。
另外看到你有用
ob_clean();
flush();
推測你前面程式碼有用了ob之類的東西才需要做這動作。
其實一般我會建議你將下載檔案寫個獨立的控制。
不要跟其它程式碼混用。
這樣你也不需要用ob方式來處理。
可以用一段程式碼來決定好要下載的檔案名稱後。再丟給下載用的model處理。這樣也不用太擔心session的問題。