获取私有文件或在HTML页面中显示私有图像 [英] Getting private files or showing private images in a HTML page

查看:128
本文介绍了获取私有文件或在HTML页面中显示私有图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何发布私人用户文件,但仅限于该用户可以访问它的方式。我的意思是,登录后,会有许多文件只有登录的用户才能访问。例如,一个图像集合或者一个mp3文件可以在html5播放器或pdf中播放下载。但重点是用户登录是文件的所有者,他是唯一可以获取文件的人。

I wonder how to publishing private user files but in the way only that user can access it. I mean, after logging in, there would be many files that only the user logged in can access. For instance, an image collection or maybe a mp3 file to play in a html5 player or a pdf to download. But the point is the user logged is the owner of the files and he is the only one who can get them.

我的问题是在HTML代码中我需要提供图像属性中的链接或html5 mp3播放器中的链接或文件链接以下载它。这个链接必须指向一个公共目录,所以每个人都可以访问它。

My problem is that in the HTML code I need to provide a link in the image attribute or a link in the html5 mp3 player or a file link to download it. And this link has to be pointing to a public directory so it can be accessed by everybody.

我的问题是:现在人们如何实现这种安全性或功能?

My question is: how do people implement that kind of security or functionality nowadays?

另一个例子。在Facebook中,您拥有自己的私人图片,即使您将任何私人图片的完整链接提供给朋友,除非您将该图片标记为公共或类似内容,否则他无法看到它。

Another example. In facebook, you have your own private images and even if you give the full link of any private image to a friend, he cannot see it unless you tag that image as "public" or something like that.

我一直在研究人们在这里给我的想法。我确实尝试过一些东西;例如,我去了Facebook并获得了我的私人形象的链接(通过右键单击并复制图像链接...)我将该链接放在其他浏览器中并在退出Facebook后,我可以看到图像在浏览器中,所以结论是文件必须在我们访问的那一刻公开。其他的事情是我们隐藏名称文件或类似的东西。

I have been researching about the ideas people have given me here. I did try some things; for instance, I went to Facebook and got the link of a private image of mine (by right clicking over and copy image link...) I put that link in other browser and after logging out of Facebook, and I can see the image in the browser so the conclusion is the file has to be public in the moment we access. Other thing is we hide the name file or something like that.

我建议:


  • 用户文件必须位于具有唯一引用的文件夹中,该名称只能知道自己的用户。所以通过将这个引用存储在像密码这样的数据库中......你明白了......

  • Users file has to be in a folder which has a "unique reference" as name that only can know the own user. So by storing this reference in a database like a password ... you got the idea...

有时,我们需要有公共文件限制访问,我的意思是,我想让人们在html5播放器或视频中播放mp3,但我不想让他们下载它。在这种情况下,我们可能会混淆代码,因此很难找到完整的链接。

Sometimes, we will need to have "public files" with limited access, I mean, I want to people to play a mp3 in the html5 player or a video, but I don't want to let them to download it. In this cases, we could obfuscate the code making it hard to find the full link.

推荐答案

好的。由于我与你的代码不一致,我将使用一些通用代码作为例子。所有你要做的就是调整它。

Alright. Since I'm unformilliar with your code, I'm going to use a bit of general code as an example. All you have to do is adjust it.

首先是一个非常基本的html,它将上传视频/ mp3 /图像或其他:

First a very basic html that will upload the video / mp3 / image or whatever:

<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>

接下来你需要准备你的数据库表:

Next you need to prepare your database table:

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的关系并不是很好。因此我在这个例子中使用PDO。但是,如果您愿意,您应该可以将其调整为MySQLi:

Now comes the file upload part. At this point I should mention that I'm not very well formilliar with MySQLi. Therefor I'm using PDO in this example. You should however be able to adjust it to MySQLi if you prefer:

<?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 扩展名的随机文件名。在我们的数据库中,我们保存这个随机文件名,原始文件名,以及它是什么类型的文件。当然,我们还添加了用户ID,因此我们知道归档的对象属于谁。这种方法的好处如下:

So what is happening? Basicly we are uploading the file to our upload dir where we give it a random filename with the .tmp extension. In our database we're saving this random filename, the original filename, and what type of file it is. Ofcourse we're adding the userid as well so we know to whom to file belongs. The benefits of this approach are as follows:


  • - 没有人知道服务器上的文件名。

  • - 除了拥有者之外,没有人会知道原始文件名。

  • - Mime类型允许我们设置我们的HTML5媒体播放器。

  • - 所有者可以下载该文件,但没有其他人。

  • - No one will ever know the file name on the server.
  • - No one will ever know the original file name except the owner.
  • - The Mime Type allows us to setup our HTML5 mediaplayer.
  • - The owner is able to download the file, but no one else.

Up文件将检索上传的文件给我们:

Up comes the PHP file that will retrieve the uploaded file for us:

<?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从数据库中检索用户文件。这样,用户根本不需要知道任何文件名!由于我们的标题,文件的所有者将能够使用它的原始名称下载文件,而根本不知道服务器上的文件名。

What is happening? In this file, you're using the file id to retrieve the users file from the database. That way no user needs to know any filename at all! Thanks to our headers, the owner of the file will however be able to download the file with it's original name, without knowing the filename on the server at all.

所以接下来我将举例说明如何向用户显示他的所有文件:

So next I will give you a short example on how to show the user all his files:

<?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媒体播放器中显示该文件。我这里只会举两个例子,你应该可以很容易地添加自己的例子:

And finally comes the PHP file that will display the file in some HTML mediaplayer. I will only 2 examples here, you should be able add your own very easily:

<?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文件。以下代码将阻止任何人访问该文件夹,但服务器本身除外:

Now to make sure no one is going to just brute force attack your uploads folder, you need to create a .htaccess file inside this folder. The following code will block anyone from accessing that folder except the server itself ofcourse:

order deny,allow
deny from all
allow from 127.0.0.1

我的 PDO类

这篇关于获取私有文件或在HTML页面中显示私有图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆