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. Each line contains a private href link to a PDF that only the logged-in user can see. The links points to various PDFs in the same folder on the server. The code works fine and I can click on the link and see each PDF.
The problem is that each PDF can also be seen by using a direct URL query (i.e. website/folder/pdfname.pdf). As these are private PDFs, I don’t want them public. I’ve tried changing CPanel permissions on the folder to “owner” – but that seems to prevent the PHP script from opening the PDFs also.
Is there a way to allow a PHP script access to PDFs in a folder – but prevent direct URL references?
NOTE: I’m not particularly adept at PHP or CPanel – sorry.
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>*
2
Answers
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 aweb.config
equivalent) to forbid access to certain files directly. If you add this snippet to that file, it will deny files with.pdf
extension: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:
or if you just do a simple scan:
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):
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). 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. Using the Content Disposition header field.
In action this works like this
1: Original page with download links – we set the cookie to work for 2 minutes
On the link page we include a hyperlink with the evaluating PHP page. Here we use JavaScript to set a cookie using the custom function
setCookie(days, hours, minutes, seconds)
, that will receive your wishes for expiry. Just note that1
is the minimum number. Not0
.2: Download page – evaluating cookie and presenting texts, or simply downloading the file
(php-secure-files-delivery-page.php)
Here we evaluate the cookie, present either the correct info or die(). Using
require_once
we get the PHP page into the current one.3: Imported file includer PHP page
(file-downloader.php)
Results
require_once
.die()
if no correct cookie was set. That cookie is only set when you want it to. On your pages. You can of course do this in JavaScript too, but that will expose the cookie, still, for most unauthorized sharing, that takes care of it.Lastly, easy security for your folder (without Apache/Nginx/.htaccess stuff)
Using .htaccess files on local folders or directives on your server is the best and most secure way. But that´s not transferable to your other applications on other systems. Instead use a
index.php
and adefault.php
page on your PDF file´s parent folder, where they are located, including this header redirect to wear off unwanted visits: