Limit access to pdf page with php

Go To StackoverFlow.com

1

With PHP, I am developing a script that generates a contract once the script is validated.

The contract is a pdf document generated with TCPDF and I save it to the server in a subdirectory with the user's ID. For example, 'contracts/132/1.pdf' would be bill #1 of user with ID 132.

However, I want only user 132 to be able to access that file, because it contains personal information. How can I limit the access to pdf documents in each subfolder to their respective user (using php or htaccess, whichever works best - I'm not very familiar with htaccess)?

2012-04-04 03:20
by Adam Strudwick


2

The easiest way is probably just to have a PHP script that requires the existence of a valid session (like the generator script does), whose function is to readfile("/path/to/contract.pdf");

That way, you can have your PDF wrapper script verify that the contract being downloaded is the RIGHT contract for the person in the sesion, not just that it's a contract that is in the directory.

The problem with a .htaccess-based solution on the directory is that anyone with read access to the directory can download ANY contract.

Given a URL like http://example.com/contract.php?user=132&bill=1 you could:

<?php

$user = $_GET['user'];
$bill = $_GET['bill'];
# do input validation on $user and $bill.  No really, do it.

if ($user != $_SESSION['user']) {
  die("Security error; the black choppers are on their way.");
}

header("Content-type: application/pdf");
header('Content-Disposition: attachment; filename="Contract-$user-$bill.pdf"');

readfile("/path/to/pdfspool/$user/Contract-$user-$bill.pdf");

The if () chunk in the middle verifies that the $user being requested is valid for the current user. Obviously, you'll want to store $_SESSION['user'], probably when this user first logs in.

Of course, you don't NEED to keep spool files, really. If the process of generating a PDF isn't going to overwhelm your web server (and if it does you have other problems), it may just be easier to re-generate each PDF from scratch, on request. That's what I do with company invoices now, and each invoice gets a 6 point footer saying when it was generated and by a request from what IP address. :)

2012-04-04 03:24
by ghoti
What if the user is wise enough to type in the direct URL to the PDF script in the address bar? For example, typing www.mysite.com/contracts/124/5.pdf - Adam Strudwick 2012-04-04 03:29
Updated. I've added a section to the code that validates $user against a session variable - ghoti 2012-04-04 03:45


2

First of all, you'd place the PDF files outside of the site's web root and retrieve them via a script.

This can be made seamless by combining a Mod_Rewrite rule that passes requests to where the PDFs would be retrieved from to a PHP script that gets user and document IDs from the URL and performs access control, which if it succeeds, outputs the file's contents.

See the PHP Manual for details on how to perform HTTP-level authentication using PHP code.

2012-04-04 03:24
by Ariel
What do you mean by "place the PDF files outside of the site's web root"? Can you illustrate it by an example - Adam Strudwick 2012-04-04 03:30
If your web root is located at /home/user/public_html, place the files in /home/user/pdfs. As long as PHP can read from the contents of the /home/user/pdfs directory, it will be able to retrieve the files' contents, but they will not be directly accessible from the web - Ariel 2012-04-04 03:32
Thanks, I hadn't thought of that - wise idea - Adam Strudwick 2012-04-04 03:34
Ads