5

我想保护 pdf 文件不被直接链接,而是让我的登录用户能够访问它。我有一个链接,该链接当前指向一个发布表单的 javascript 函数: $('nameofdoc').setProperty('value',doc); document.getElementById('sendme').submit();

其中 sendme 是表单的名称,而 nameof doc 是我要显示的文档的索引。

然后转到一个 php 文件:

 $docpath = $holdingArray[0].$holdingArray[1];

 $file = $holdingArray[0]; //file name
 $filename = $holdingArray[1]; //path to the file]
 header( 'Location:'.$docpath ) ;
 header('Content-type: application/pdf');
 header('Content-Disposition: attachment; filename="'.$filename  . '"');
 readfile($filename)

这一切都很好,它加载文件并输出pdf。我不能做的是保护目录免受直接链接 - 即 www.mydomain.com/pathToPdf/pdfname.pdf

我曾想过使用 .htaccess 来保护目录,但它位于共享主机上,所以我不确定安全性,无论如何,当我尝试过时,我无法让它工作。

任何帮助都会很棒,因为这是我尝试解决此问题的第四天。

谢谢

更新

我得到了很多帮助,谢谢你,但我还没到那里。

我有一个 .htaccess 文件,当从目录请求 pdf 时,它现在会启动另一个 php 文件:

 RewriteEngine on
 RewriteRule ^(.*).(pdf)$ fileopen.php

当 fileopen.php 文件启动时,它无法打开 pdf

 $path = $_SERVER['REQUEST_URI'];
 $paths = explode('/', $path);
 $lastIndex = count($paths) - 1;
 $fileName = $paths[$lastIndex]; 

 $file = basename($path);

 $filepath = $path;

 if (file_exists($file)) {
     header( 'Location: http://www.mydomain.com'.$path ) ;
     header("Content-type: application/pdf");
     header("Content-Disposition: attachment; filename=".$file);
     readfile($filepath);

 }else{
     echo "file not found using path ".$path." and file is ".$file;
 }

输出是使用路径 /documents/6/Doc1.pdf 找不到文件,文件是 Doc1.pdf

但是该文件确实存在并且在那个目录中-有什么想法吗?

好的,我很高兴地报告 Jaroslav 确实帮助我解决了这个问题。他的方法效果很好,但很难将所有目录内容排成一行。最后,我花了几个小时玩弄组合来让它发挥作用,但他给出的原则运作良好。谢谢

4

3 回答 3

8

正如您所提到的,最好的方法是使用 htaccess 保护该文件夹。因此,您将所有 PDF 文件放在 pdf/ 文件夹中,并在同一个 pdf 文件夹中取出 .htaccess 文件:

RewriteEngine on
RewriteRule .* your-php-script.php

现在此文件夹中的 url 无法访问任何文件。对该文件夹中每个文件的每个请求都将返回 your-php-script.php 脚本返回的内容。在 your-php-script.php 你做这样的事情:

//Check if user has right to access the file. If no, show access denied and exit the script.
$path = $_SERVER['REQUEST_URI'];
$paths = explode('/', path);
$lastIndex = count($paths) - 1;
$fileName = $paths[$lastIndex]; // Maybe add some code to detect subfolder if you have them
// Check if that file exists, if no show some error message
// Output headers here
readfile($filename);

现在,如果用户打开 domain.com/pdf/nsa-secrets.pdf Apache 将运行 your-php-script.php。脚本将变量 $_SERVER['REQUEST_URI'] 设置为“domain.com/pdf/nsa-secrets.pdf”。您获取最后一部分(文件名)并将其输出给用户(或不输出)。

这将阻止任何人通过知道 URL 直接从 Internet 访问文件。如果有人可以直接访问您服务器上的文件,这不会阻止他们。另一方面,我认为任何共享主机都会阻止用户获取其他客户端的文件。唯一的办法就是以某种方式破解服务器。但是后来我们变得非常偏执,如果您可能遇到这种情况,那么您首先不应该使用共享主机。

如果您无法使 htaccess 正常工作,您可以尝试混淆文件,因此很难为外面的人发现它们。例如将文件从 mySecretData.pdf 更改为 djjsdmdkjeksm.pdf。这可能会有所帮助。

于 2013-10-01T19:36:22.787 回答
1

我想保护 pdf 文件不被直接链接,而是让我的登录用户能够访问它。

在流式传输 PDF 内容之前检查以确保有经过身份验证的用户。

于 2013-10-01T19:18:10.683 回答
0

这有点草率,但假设您可以设置 MYSQL DB,它可以工作。它允许您将 URL 中的“密码”作为 MD5 字符串传递,或者如果您愿意,可以作为明文传递。尝试在不使用 htaccess 或现有框架的情况下设置某种安全性有点笨拙。但是,这甚至不会将文件附加到流中,直到它知道您已“经过身份验证”为止在 URL 中传递“密码”。

    $file = $_GET['file'];
    $pass = $_GET['pass'];
    $download_folder = '../Protected';
    $file = basename($file);
    $filepath = "$download_folder/$file";

    if (file_exists($filepath)) {
        if(CheckUser($pass)){
            header("Content-type: application/octet-stream");
            header("Content-Disposition: attachment; filename=$file");
            session_write_close();
            readfile($filepath);
        } else {
            echo 'Not Authenticated!';
        }
    } else {
        echo 'No File!';
    }

function CheckUser($value){
    $con = mysqli_connect("test.com","test","123456","my_db");
    // Check connection
    if (mysqli_connect_errno()){
        echo "Failed to connect to MySQL: " . mysqli_connect_error();
    }
    $result = mysqli_query($con,"SELECT user FROM pass_table WHERE password =".md5($value).";");
    while($row = mysqli_fetch_array($result)){
        mysqli_close($con);
       //return $row['user'];
       if($row['user']){
           return true;
       }
    }
    mysqli_close($con);
    return false;

}
于 2013-10-01T19:43:44.703 回答