PHP使安全内容可用

时间:2014-05-27 17:01:43

标签: php security

我的问题不是针对任何编码问题,而是针对某种指导。我需要安全地下载pdf文件(非密码保护文件),以便只有经过身份验证的用户才能下载该文件。

我能想到的是将所有pdf文件存储在根目录之外,然后将文件随机生成的名称临时复制到公共场所并使其可用。有什么意见吗?

或者是否有办法每次使用新密码保护pdf文件,并在下载前通知经过身份验证的用户密码(问题的一半是用户忘记了pdf密码,因此我们正在考虑采用其他策略)。

感谢任何建议或意见。

3 个答案:

答案 0 :(得分:2)

你也可以这样做:

使用digest auth登录用户,然后才能下载

http://www.php.net/manual/en/features.http-auth.php

<强> test.php的

<?php

$realm = 'Restricted area';

// user => password
// this can come from your DB
$users = array('myuser' => 'mypass');

// Send Login Request
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
    die('Text to send if user hits Cancel button');
}

// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');

// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, valid username & password
// send pdf file
$file_url = "http://fzs.sve-mo.ba/sites/default/files/dokumenti-vijesti/sample.pdf";
header('Content-Type: application/pdf');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=". basename($file_url));
readfile($file_url);
exit();

// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}

?>

答案 1 :(得分:1)

如果您想让用户直接访问PDF文件(即它在文档根目录中),您可以在PDF所在的目录中创建.htaccess。例如,您可以拥有:

RewriteEngine On
RewriteRule ^(.*) check.php?file=$1 [L]

然后,在check.php中,您可以:

$file = realpath(__DIR__ . "/" . $_GET["file"]);

if(!preg_match("/^" . preg_quote(__DIR__, "/") . "/", $file))
{
    // Prevent someone from using relative paths in the URL
    die("Invalid file path");
}
elseif(!file_exists($file))
{
    die("File doesn't exist");
}
elseif(!SOME_PERMISSION_CHECK)
{
    die("You do not have access to these files");
}

header("content-type: application/pdf");
header("content-length: " . filesize($file), true);
readfile($file);

答案 2 :(得分:0)

如果用户在下载任何内容之前已经对您的系统进行了身份验证,则可以通过在#34;之间使用php脚本来单独绕过保护文件。用户和pdf。

像这样的东西(为了示例目的简化):

if ($_SESSION['user_authenticated']){
    $pdf_info = read_pdf_metadata($pdf_id);
    header('Content-type: application/pdf');
    header("Content-disposition: filename=".$pdf_info['filename']);
    echo file_get_contents($pdf_info['file_path']);      
}

标题可能有点不稳定(我有一段时间没与它们合作过,而且正在从它们的臀部拍摄),但该代码基于拥有数据库表或其他数据源的想法存储在文档根目录之外的PDF文件。使用类似的东西,你永远不必发送直接链接到PDF本身。