[英]Allow a PHP script access to PDFs in a folder - but prevent direct URL references
On a godaddy hosted website using CPanel, I have a small PHP script that shows each line in a text file that's on the server.在使用 CPanel 的 Godaddy 托管网站上,我有一个小的 PHP 脚本,它显示服务器上文本文件中的每一行。 Each line contains a private href link to a PDF that only the logged-in user can see.
每行包含一个指向 PDF 的私有 href 链接,只有登录用户才能看到。 The links points to various PDFs in the same folder on the server.
这些链接指向服务器上同一文件夹中的各种 PDF。 The code works fine and I can click on the link and see each PDF.
代码运行良好,我可以单击链接并查看每个 PDF。
The problem is that each PDF can also be seen by using a direct URL query (ie website/folder/pdfname.pdf).问题是每个 PDF 也可以通过使用直接 URL 查询(即网站/文件夹/pdfname.pdf)来查看。 As these are private PDFs, I don't want them public.
由于这些是私人 PDF,我不希望它们公开。 I've tried changing CPanel permissions on the folder to "owner" - but that seems to prevent the PHP script from opening the PDFs also.
我已经尝试将文件夹上的 CPanel 权限更改为“所有者”——但这似乎也阻止了 PHP 脚本打开 PDF。
Is there a way to allow a PHP script access to PDFs in a folder - but prevent direct URL references?有没有办法允许 PHP 脚本访问文件夹中的 PDF - 但防止直接 URL 引用?
NOTE: I'm not particularly adept at PHP or CPanel - sorry.注意:我不是特别擅长 PHP 或 CPanel - 抱歉。
Code...代码...
$fname = "PDF-" . $user_name.".txt";
$fnum = fopen($fname,"r");
echo "<tr>";
While (($str = fgets($fnum)) !== false) {
$arr = explode("|",$str);
for ($x = 0 ; $x < count($arr); $x++) {
echo "<td>$arr[$x]</td>";
}
echo "</tr>";
}
echo "</tr>";
fclose($fnum);
File contents...文件内容...
Xyz Company|21 Jan 2018|<a href="http://website.com"> website link</a>
Xyz Company|21 Jan 2018|<a href="http://website.com"> website link</a>
Xyz Company|21 Jan 2018|<a href="http://website.com"> website link</a>
Xyz Company|21 Jan 2018|<a href="http://website.com"> website link</a>*
Asside from removing the files from the root, if you are running apache, you can change your .htaccess
(I'm sure windows-based system have a web.config
equivalent) to forbid access to certain files directly.除了从根目录中删除文件之外,如果您正在运行 apache,您还可以更改
.htaccess
(我确信基于 Windows 的系统具有web.config
等效项)以禁止直接访问某些文件。 If you add this snippet to that file, it will deny files with .pdf
extension:如果将此代码段添加到该文件,它将拒绝扩展名为
.pdf
文件:
<FilesMatch "\.(pdf)$">
Order Allow,Deny
Deny from all
</FilesMatch>
From there, inside your app, you can create some sort of system for curating your PDF links, so if you store the real path in a database and use the id as the link similar to:从那里,在您的应用程序中,您可以创建某种系统来管理您的 PDF 链接,因此如果您将真实路径存储在数据库中并使用 id 作为类似于以下内容的链接:
http://www.example.com/?file=1
or if you just do a simple scan:或者如果你只是做一个简单的扫描:
<?php
# The folder that the PDFs are in
$dir = __DIR__.'/website/folder/';
# Loop over a scan of the directory (you can also use glob() here)
foreach(scandir($dir) as $file):
# If file, create a link
if(is_file($dir.$file)): ?>
<a href="?action=download&file=<?php echo $file ?>"><?php echo $file ?></a>
<?php
endif;
endforeach;
Then, if the user tries to download using the link, you check they are first logged in and if they are, download the file by doing a script like so BEFORE you output anything else to the browser (including spaces) :然后,如果用户尝试使用链接下载,您检查他们是否首先登录,如果他们是,请在向浏览器输出任何其他内容(包括空格)之前通过执行如下脚本下载文件:
<?php
session_start();
# First check that the user is logged in
if(empty($_SESSION['username']))
die('You must be logged in to download this document.');
# Not sure which directory you are currently in, so I will assume root
# I would do basename() here incase the user tries to add in something like:
# ../index.php and tries to download files they are not supposed to
$file = __DIR__.'/website/folder/'.basename($_GET['file']);
if(!is_file($file))
die('File does not exist.');
# Double check that the file is a pdf
elseif(strtolower(pathinfo($file, PATHINFO_EXTENSION)) != 'pdf')
die('File appears to be invalid.');
# Start download headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
One simpler and basic example (and derivative of previous answer) is to use two separate PHP files , where one is evaluating a set cookie (set to expire soon) in the browser upon link click (set via JS or PHP or other).一个更简单和基本的示例(以及先前答案的派生)是使用两个单独的 PHP 文件,其中一个是在点击链接(通过 JS 或 PHP 或其他设置)时在浏览器中评估设置的 cookie(设置为即将过期)。 If the cookie was read correctly, the first PHP page imports a second page that utilizes the PHP header() redirect containing your original file name forcibly downloaded with another name .
如果 cookie 被正确读取,第一个 PHP 页面会导入第二个页面,该页面利用 PHP header()重定向,其中包含您用另一个名称强行下载的原始文件名。 Using the Content Disposition header field.
使用内容处置标头字段。
<a onclick="setCookie(1, 1, 2, 60)" href="php-secure-files-delivery-page.php">Download My Final PDF name.pdf</a>
<script type="text/javascript">
// set a cookie with your own time limits.
function setCookie(days, hours, minutes, seconds) { // Create cookie
var expires;
var date = new Date();
date.setTime(date.getTime()+(days*hours*minutes*seconds*1000));
expires = "; expires="+date.toGMTString();
document.cookie = "my_cookie_name"+"="+"my_cookie_value"+expires+"; path=/";
}
</script>
On the link page we include a hyperlink with the evaluating PHP page.在链接页面上,我们包含一个带有评估 PHP 页面的超链接。 Here we use JavaScript to set a cookie using the custom function
setCookie(days, hours, minutes, seconds)
, that will receive your wishes for expiry.在这里,我们使用 JavaScript 使用自定义函数
setCookie(days, hours, minutes, seconds)
设置 cookie,它将接收您的到期愿望。 Just note that 1
is the minimum number.请注意,
1
是最小数字。 Not 0
.不是
0
。
(php-secure-files-delivery-page.php) (php-secure-files-delivery-page.php)
<?php
// if the cookie is set correctly, load the file downloader page.
if (isset($_COOKIE['my_cookie_name'] && $_COOKIE['my_cookie_name'] === 'my_cookie_value')) {
require_once 'file-downloader.php'; // the file will force the download upon import.
} else {
die('The link expired, go to your downloads section and click on the link again.');
}
?>
Here we evaluate the cookie, present either the correct info or die().在这里,我们评估 cookie,显示正确的信息或 die()。 Using
require_once
we get the PHP page into the current one.使用
require_once
我们让 PHP 页面进入当前页面。
(file-downloader.php) (文件下载器.php)
<?php
// We'll be outputting a PDF
header('Content-Type: application/pdf');
// It will be downloaded as your-downloaded.pdf
header('Content-Disposition: attachment; filename="your-downloaded.pdf"');
// The PDF source is in your own specified long name
readfile('original-with-really-weird-original-name.pdf');
?>
require_once
.require_once
。die()
if no correct cookie was set.die()
。 That cookie is only set when you want it to. Using .htaccess files on local folders or directives on your server is the best and most secure way.在服务器上的本地文件夹或指令中使用 .htaccess 文件是最好和最安全的方式。 But that´s not transferable to your other applications on other systems.
但这不能转移到其他系统上的其他应用程序。 Instead use a
index.php
and a default.php
page on your PDF file´s parent folder, where they are located, including this header redirect to wear off unwanted visits:而是在您的 PDF 文件的父文件夹上使用
index.php
和default.php
页面,它们所在的位置,包括此标题重定向以消除不需要的访问:
<?php
header("Location: http://yoursite.com/some-other-page/"); /* Redirect browser here */
?>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.