Reputation: 1184
I'm trying to show my PDF files in my webpages but block the direct access to the files. I'm trying to do this by using a .htaccess file like this:
order deny,allow
deny from all
allow from {MY_IP}
Where MY_IP is my server IP address (ex. 11.22.333.444), but when I do this my server can't access the files anymore. I'm showing the PDF's with this code:
<object data="downloads/PDF/doc.pdf" type="application/pdf" width="100%" height="100%">
<p>It appears you don't have a PDF plugin for this browser.
You can <a href="doc.pdf">click here to
download the PDF file.</a></p>
</object>
The webpage just stays blank (it can't load it). Is there anything I'm missing with .htaccess?
Thanks for helping in advance!
Marc
Upvotes: 0
Views: 2031
Reputation: 7870
You can check the referring website to see if it's your own with .htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST}@@%{HTTP_REFERER} !^([^@]*)@@http?://\1/.*
RewriteRule .*\.pdf [NC,F]
That will fail with a forbidden directive (403 error). NC is case insensitivity. The server would need to be configured to show something in the event of a 403 error.
In PHP Additionally you can check this sort of thing with a dynamic page that allows the download. Here's an example of how to do this with PHP:
<a href='/download.php?f=myfile&fd=mypath'>Download my PDF</a>
We're taking the .pdf
off of the name in the link for security reasons. You could do something like base64_encode
the name, but this won't stop a knowledgeable attacker from trying to exploit your system. The f
variable is the filename (pre-period) and the 'fd' would be the folder (or path).
Example dirs could include pdfs
or resources/pdf
.
It can't start or end with a /
. We're not allowing periods in paths or filenames so someone can't do something like pdf/../../..
.
Code for download.php
<?php
if((preg_match('!^[A-Za-z0-9_-]+$!',$_GET['f']))&&(preg_match('!^[^/][/A-Za-z0-9_-]+[^/]$!',$_GET['fd']))){
//we're hard-coding the line so someone can't spoof something like .htaccess
$tempPath = $_GET['fd'];
$tempFilename = $_SERVER['DOCUMENT_ROOT'].'/'.$tempPath.'/'.$_GET['f'].'.pdf';
//Make sure it's a real file
if(is_file($tempFilename)){
$referrer = $_SERVER['HTTP_REFERER'];
$serverName = $_SERVER['SERVER_NAME'];
//check the referrer
if(strpos($referrer, $serverName)){
$new_filename = $_GET['f'].'.pdf';
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
$hString = 'Content-Disposition: attachment; filename="'.$new_filename.'"';
header($hString);
// The PDF source is in original.pdf
readfile($tempFilename);
} else {
//offsite link
header('Location: /download_policy.php');
exit();
}
} else {
//maybe an old file? Give them the homepage
header('Location: /');
exit();
}
} else {
//hacking attempt
header('Location: /');
exit();
}
?>
Upvotes: 3