2015-09-05 53 views
3

我想知道如何發佈私人用戶文件,但是隻有該用戶才能訪問它。我的意思是,登錄後,會有許多文件只有用戶登錄才能訪問。例如,一個圖像採集或者一個mp3文件可以在html5播放器中播放或者下載一個pdf文件。但關鍵是用戶登錄是文件的所有者,他是唯一可以獲得這些文件的人。獲取私人文件或在HTML頁面中顯示私人圖像

我的問題是,在HTML代碼中,我需要提供圖像屬性中的鏈接或html5 mp3播放器中的鏈接或文件鏈接以下載它。這個鏈接必須指向一個公共目錄,以便每個人都可以訪問它。

我的問題是¿當今人們如何實現這種安全或功能?

另一個例子。在臉書上,你有自己的私人圖像,即使你把任何私人圖像的完整鏈接給朋友,他也不能看到它,除非你將該圖像標記爲「公開」或類似的東西。

非常感謝!

======================可能的解決方案=====================

我一直在研究人們在這裏給我的想法,謝謝你們......我做了任何嘗試,例如,我去了facebook並獲得了我的私人圖像的鏈接(通過右鍵單擊並複製圖像鏈接...)我把這個鏈接放在其他瀏覽器中,在loggout facebook之後,我可以在瀏覽器中看到這個圖像,所以我們訪問的時候文件必須公開。其他的事情是我們隱藏名字文件或者類似的東西。

我建議:

  • 用戶文件必須具有「唯一參考」作爲名稱,只有知道自己的用戶文件夾中。所以通過將這個引用存儲在數據庫中,如密碼...你有這個想法...

  • 有時,我們需要有「公共文件」,有限訪問,我的意思是,我想讓人們玩在HTML5播放器或視頻中的MP3,但我不想讓他們下載它。在這種情況下,我們可以這樣做: - 混淆代碼使得很難找到完整鏈接 - ?

==============請給更多的想法,所以我可以總結everithing =========

感謝: -icecub -Darren H -Rohit Gupta

+0

這是一個非常廣泛的主題,恐怕不能在這裏介紹。有很多種方法可以實現這一點。做它服務器端將是最好的,因爲訪問者總是可以修改JavaScript。 –

+0

我發現最安全的選擇是將用戶文件保存在文檔根目錄之外。但是,要完成此操作,您需要完全訪問您的服務器。默認情況下,php不能遍歷文檔根目錄之外。所以你需要做一些調整來實現這一點。完成後,根本沒有任何直接鏈接到可以工作的文件。然而,Php本身可以訪問它們並將它們返回給用戶。 – icecub

+0

非常感謝Darren H,你知道涵蓋這個問題的任何資源或教程嗎?我沒有找到GOOGLING :-( – user2992476

回答

1

好的。由於我對代碼不熟悉,因此我將使用一些通用代碼作爲示例。你所要做的就是調整它。

首先將視頻上傳/ MP3 /圖片或任何一個非常基本的HTML:你需要準備你的數據庫表

<form name="upload" action="" method="POST" ENCTYPE="multipart/form-data"> 
    Select the file to upload: <input type="file" name="userfile"> 
    <input type="submit" name="upload" value="upload"> 
</form> 

下一頁:

CREATE TABLE `uploads` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `userid` INT(11) NOT NULL, 
    `name` VARCHAR(64) NOT NULL, 
    `original_name` VARCHAR(64) NOT NULL, 
    `mime_type` VARCHAR(20) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 

現在到了文件上傳部分。在這一點上,我應該提到,我並不擅長MySQLi的formilliar。爲此,我在這個例子中使用了PDO。但是,如果您願意,您應該可以將其調整爲MySQLi:

<?php 
session_start(); 
# My PDO class. A link to it can be found at the bottom of this answer 
require_once 'pdo.class.php'; 

# Send user back login if not logged 
if(!isset($_SESSION['your_login_userid_here'])){ 
    Header("Location: your_login.php"); 
} 

# If file is uploaded 
if(isset($_POST['upload'])){ 
    $uploaddir = 'uploads'; # Your upload directory 

    function tempnam_sfx($path, $suffix){ 
     do { 
      $file = $path."/".mt_rand().$suffix; 
      $fp = @fopen($file, 'x'); 
     } 
     while(!$fp); 

     fclose($fp); 
     return $file; 
    } 

    # Make a regular expression to check for allowed mime types 
    $pattern = "#^(image/|video/|audio/)[^\s\n<]+$#i"; 

    if(!preg_match($pattern, $_FILES['userfile']['type']){ 
     die("Only image, video and audio files are allowed!"); 
    } 

    $uploadfile = tempnam_sfx($uploaddir, ".tmp"); 

    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { 

     # Define db configuration 
     define("DB_HOST", "localhost"); 
     define("DB_USER", "username"); 
     define("DB_PASS", "password"); 
     define("DB_NAME", "dbname"); 

     $db = new Database; 

     $db->query("INSERT INTO uploads SET userid=:id, name=:filename, original_name=:oriname, mime_type=:mime"); 

     $db->bind(":userid",$_SESSION['your_login_userid_here']); 
     $db->bind(":filename",basename($uploadfile)); 
     $db->bind(":oriname",basename($_FILES['userfile']['name'])); 
     $db->bind(":mime",$_FILES['userfile']['type']); 

     try { 
      $db->execute(); 
     } catch (PDOException $e) { 
      unlink($uploadfile); 

      die("Error saving data to the database. The file was not uploaded"); 
     } 

     $id = $db->lastInsertId(); 
     echo "File succesfully uploaded.\n"; 

    } else { 
     echo "File uploading failed.\n"; 
    } 
} else { 
    # No upload received. Send user to upload page 
    Header("Location: html_upload_form.html"); 
} 

?> 

那麼發生了什麼?基本上我們正在上傳文件到我們的上傳目錄,我們給它一個隨機的文件名,其擴展名爲.tmp。在我們的數據庫中,我們保存了這個隨機文件名,原始文件名以及它的類型。當然,我們也添加了用戶標識,所以我們知道應該向誰提交文件。這種方法的好處如下:

  • - 沒有人會知道服務器上的文件名。
  • - 除了所有者之外,沒有人會知道原始文件的名稱。
  • - Mime Type允許我們設置HTML5媒體播放器。
  • - 所有者能夠下載文件,但沒有其他人。

最多而來的PHP文件,將檢索我們上傳的文件:

<?php 
session_start(); 
require_once 'pdo.class.php'; 

# Send user back login if not logged 
if(!isset($_SESSION['your_login_session_here'])){ 
    Header("Location: your_login.php"); 
} 

# Define db configuration 
define("DB_HOST", "localhost"); 
define("DB_USER", "username"); 
define("DB_PASS", "password"); 
define("DB_NAME", "dbname"); 

$uploaddir = 'uploads/'; 
$id = $_GET['id']; 

if(!is_numeric($id)) { 
    die("File id must be numeric"); 
} 

$db = new Database; 

$db->query('SELECT userid, name, mime_type FROM uploads WHERE id=:id'); 

$db->bind(":id", $id); 

try { 
    $file = $db->single(); 
} catch (PDOException $e) { 
    die("Error fetching data from the database"); 
} 

# Check if file belongs to user 
if($_SESSION['your_login_session_here'] != $file['userid']){ 
    die("This file does not belong to you!"); 
} 

if(is_null($file) || count($file)==0) { 
    die("File not found"); 
} 

$newfile = $file['original_name']; # The original filename 

# Send headers and file back 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename='.basename($newfile)); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate'); 
header('Pragma: public'); 
header('Content-Length: ' . filesize($uploaddir.$file['name'])); 
header("Content-Type: " . $file['mime_type']); 
readfile($uploaddir.$file['name']); 

?> 

這是怎麼回事?在此文件中,您使用文件ID從數據庫檢索用戶文件。這樣,用戶不需要知道任何文件名!得益於我們的頭文件,文件的所有者將能夠使用它的原始名稱下載文件,而不必知道服務器上的文件名。

所以接下來我會給你如何向用戶展示他所有的文件一個簡單的例子:

<?php 
session_start(); 
require_once 'pdo.class.php'; 

# Send user back login if not logged 
if(!isset($_SESSION['your_login_session_here'])){ 
    Header("Location: your_login.php"); 
} 

# Define db configuration 
define("DB_HOST", "localhost"); 
define("DB_USER", "username"); 
define("DB_PASS", "password"); 
define("DB_NAME", "dbname"); 

$db = new Database; 

# Retrieve all files from the user and build links 
$db->query("SELECT id, original_name, mime_type FROM uploads WHERE userid=:id"); 

$db->bind(":id",$_SESSION['your_login_session_here']); 

try { 
    $files = $db->resultset(); 
} catch (PDOException $e) { 
    die("Error fetching data from the database"); 
} 

if($db->rowCount() > 0){ 
    foreach($files as $file){ 
     echo "<a href='your_html_viewer_file.php?id=". $file['id'] "&type=". $file['mime_type'] .">". $file['original_name'] ."</a><br />"; 
    } 
} else { 
    echo "No files found!"; 
} 

?> 

最後談到的PHP文件,將顯示一些HTML媒體播放器的文件。我會在這裏只有2個例子,你應該能夠添加自己很容易:

<?php 
session_start(); 

# Send user back login if not logged 
if(!isset($_SESSION['your_login_session_here'])){ 
    Header("Location: your_login.php"); 
} 

$id = $_GET['id']; 
$type = $_GET['type']; 

if(strpos($type, 'video/') === 0){ ?> 

    <video width="480" height="320" controls> 
     <source src="your_file_retriever.php?id=<?php echo $id; ?>" type="<?php echo $type; ?>"> 
    </video> 

<?php } else if(strpos($type, 'audio/') === 0){ ?> 

    <audio controls> 
     <source src="your_file_retriever.php?id=<?php echo $id; ?>" type="<?php echo $type; ?>"> 
    </audio> 

<?php } ?> 

現在,以確保沒有人會只是蠻力攻擊你上傳的文件夾,你需要創建裏面.htaccess文件這個文件夾。下面的代碼將訪問除了服務器本身ofcourse該文件夾阻止任何人:

order deny,allow 
deny from all 
allow from 127.0.0.1 

PDO Class

+0

這是非常好的解決方案的人!非常感謝!!我正在尋找嘗試! – user2992476

+0

@ user2992476感謝您的讚賞。如果出現任何問題,請告知我,我會盡我所能解決這些問題。 – icecub

0

有許多解決方案。我用於約會網站的一個是具有與用戶的唯一引用相同的文件夾名稱。那裏的所有文件都屬於該用戶。然而,訪問仍然由PHP提供正確的鏈接在HTML中控制。

這是簡單的答案。因爲我不希望圖像文件夾中的子文件夾的數量爲數千個,我將它們散列到另一個級別的文件夾中。

+0

非常感謝Rohit Gupta,所以,在你的解決方案中,重點是隻有用戶擁有者知道唯一的參考文件(文件夾名稱),所以文件仍然是公開的,獨特的參考文件就像一個「私鑰「不是嗎? – user2992476

+0

在我的使用中,這些文件都是隻讀的,任何人都可以看到它們。如果用戶想要編輯或替換它們,那麼這是通過一個新的臨時隨機命名文件夾來實現的。在你的情況,上面的答案存儲問題。您仍然必須整理適合的安全性。 –