2015-09-05 125 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

在我的使用中,这些文件都是只读的,任何人都可以看到它们。如果用户想要编辑或替换它们,那么这是通过一个新的临时随机命名文件夹来实现的。在你的情况,上面的答案存储问题。您仍然必须整理适合的安全性。 –