I am deploying a website from where user can purchase the pdfs. now i am searching for the way for storing the pdfs so that it only can be downloaded when payment is done.
I have came across one way in which i can store the pdfs in to the Mysql database and generate the path to it when required credentials fulfill.
Is there any other way to do this and link to the pdf file should be dynamic and encrypted so that other links to the other books can't be predicted.
and the server side language I am using is PHP
You need to store the files somewhere outside your website root like mentioned by Dagon. When file is uploaded use move_uploaded_file to move it. You can name the file anything you want (within OS limits) and keep the real name in the database.
Then when the user has payed for the books, add the books the user has payed for to a table in a db.
Give the user a list of all the books he has payed for like: /download/filename.pdf
Add a mod_rewrite if you use Apache (or equivalent for other web servers) where /download/.* is redirected to download.php or a controller.
On the download page, check if user is logged in and has access to the file. If not, redirect to purchase page for that book.
If download is ok set header for the http status you need: Content-Length, Content-Type, Date, Status (200), maybe Content-Encoding.
Use readfile to output the file to the end user.
I would :
Deny any access to the files -- i.e. use a .htaccess file (That way, no-one has access to the file)
Develop a PHP script that would :
receive a file identifier (a file name, for instance ; or some identifier that can correspond to the file)
authenticate the users (with some login/password fields), against the data stored in the database if the user is valid, and has access to the file (This is if different users don't have access to the same set of files), read the content of the file from your PHP script, and send it the the user.
The advantage is that your PHP script has access to the DB -- which means it can allow users to log-in, log-out, it can use sessions, ...
Here is another answer from a stack user that fits this problem: Creating a Secure File Hosting Server for PDFs
is there any other way to do this and link to the pdf file should be dynamic and encrypted so that other links to the other books can't be predicted.
The best way, is after payment generate a key to the file.
create a page like this www.site.com/download.php?key=key (and here you don't need to have id of the book, because by the key you can check on the database what is the book the customer purchased.
inside the download.php read the key, query the database to find which file is linked with the key
read the file, and send it to the customer. This is, if the key is valid, you will send the php headers as content type as being pdf, and (the php code) read the file in binary and send it in the message body.
I hope this code helps
<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('original.pdf');
?>
Related
I want to build e-commerce website with php and I will use omnipay library for paying. The problem is if the file in the url www.mywebsite.com/programs/paint.exe the user can write in his browser that url and the paid program will download..... I searched how to block user from downloading file like RewriteEngine but how can I let the file download if the user paid in this case?
Maybe you can try these :
Store your program name in hashed format, so instead of www.mywebsite.com/programs/paint.exe maybe it's better in something like this www.mywebsite.com/programs/ca63ff966ff272da14e4fc2e73fcd399. You atleast have store your paid programs in a table and that table should provide its hash formatted name column.
www.mywebsite.com/programs/paint.exe this url should and only accessible by authenticated user. And if it's already authenticated users, you check this user's purchase history, if he/she ever buy this paint.exe program, if there is no record of his/her purchase, you must redirect he/she to your payment page.
In addition to using hashed filenames as Peter mentioned, you can use php to serve the file after authentication.
Create an htaccess rewrite to send any requests for the file directly to a php script. In the php script, perform some authentication (I.E. have the user login, or have them use a secured link which sets session variables, etc.). Then, if the user authenticated successfully, use php to return the file using http headers.
header('Content-Type: application/x-msdownload'); // Set this to a .exe
header('Content-Disposition: attachment; filename="paint.exe"'); // Set the filename to download.
$downloadFile = file_get_contents('programs/hashedpaintexename.exe');
echo $downloadFile;
NOTE: You will want to make sure that should you use hashed filenames you'll want your htaccess handle these hashed files as well.
Another option, if you've got the control over the server to do so, is you can have PHP load the file from outside of the website's directory instead of using a htaccess rewrite. For example, if your website directory is /var/www/mywebsite, have php load the executable from /whatever/path/you/want provided php has read-access to the directory.
My question seems to be similar to others here in SO, I have try a few but it doesn't seem to work in my case...
I have develop a site in which you have to fill up a form and then it returns a PDF file that you can download or print, this file is saved so you can retrieve it later
public_html
|_index.php
|_<files>
| |_file_001.pdf
| |_file_002.pdf
|_<asstes> ....etc
that is how my files and folders look on the server, anyone can easily guess other files, .com/folder/file_00X.pdf, where X can be change for any other number and get access to the file... the user after finish with the form the script returns a url .com/file/file_001.pdf so he/she can click on it to download...
a year ago I did something similar an script to generate PDF's but in that case the user needed the email and a code that was sent via email in order to generate the PDF and the PDF's are generated on demand not saved like in this case...
Is there a way to protect this files as they are right now?
or, do I have to make it a little bit more hard to guess?
something like.
.com/files/HASH(MD5)(MICROTIME)/file_(MICROTIME)_001.pdf
and save the file and folder name in the DB for easy access via admin panel, the user will have to get the full URL via email...
Any ideas would be greatly appreciated.
For full security i would move the PDFs out of the public folder and have ascript in charge of delivering the content. If the form is filled correctly, you can generate a temporary hash and store that hash and the pdf path in the database. That way the user will have access to the file as a link through the retriever script, but you will control for how long he will have that link available.
Imagine the temporary link being http://yourdomain/get_pdf/THIS_IS_THE_HASH
Move the PDF's to some non-public folder (that your web server has access to but the public does not). Or you can use .htaccess to restrict access to the pdf's in their current location.
Write a php script that returns the correct pdf based on some passed in http variable.
You can secure/restrict this any way that you want to.
For example, one answer suggested using a temporary hash.
Other options for restricting access:
Store in the user's session that they submit the form and have a download pending, that way no one could direct link.
Check the referrer header. If it is a direct request then do not serve the file.
Here is a code example using the last option:
$hash_or_other_identifier = $_REQUEST["SomeVariable"];
if (!$_SERVER["HTTP_REFERER"])
{
//dont serve the file
} else {
//lookup the file path using the $hash_or_other_identifier
$pdfFile = somelogic($hash_or_other_identifier);
//serve the correct pdf
die(file_get_contents($pdfFile));
}
I don't even think that keeping the file name secret is a very big deal if all you are worried about is people typing it into the URL bar because you can simply check if it is a direct link or not. If you are also worried about bots or clever people who will create a link that points to your file so it looks like a referrer, then you will need to add stricter checks. For example, you can verify that the referrer is your own site. Of course headers can be spoofed so it all just depends how bulletproof it needs to be.
The url would be something like: http://yourdomain/pdf?SomeVariable=12345
However, you don't have to use an http variable. You can also use a url fragment with the same result, eg: http://yourdomain/pdf/12345
General guidelines:
File is not in the directory that's accessible via HTTP
Use a database or any other storage to link up file location with an identifier (an auto incremented number, guid, hash, whatever you deem fit). The location of the file could be in the server's file system or on a shared network location etc.
Instead of hashes, it's also practical to encrypt the ID generated by the database, base64 encode it and provide it back - that makes it nearly impossible to guess the valid string that one needs to send back in order to refer to a file
Use a PHP script that delivers the file if user authentication passes (in case you need authenticated users to be able to retrieve the file)
What is considered the best way to code which will allow user to save table data by clicking "save as"
Here is the scenario
I've created a web page that list data from a mysql db (app created in php).
The page lists the data and provides a "Save as" button so the data can be save to the users local computer (csv, xml, etc.).
Technical
Is the following the best way to do this
1) save the data to a file from in the same php program that queried that mysql db?
2) when user clicks "save as" on web page, ajax streams the data from #1 (server) to the users local computer
I've read a few things on how to create xml data (opendocument, openxml) and php excel/xml libs but just don't completely understand the flow; should a file be created at time of query, how does the data get to the users local computer, etc. Or is there a different approach to do this?
Thanks
There are mostly two approaches:
Generate a file on the server. You can do this before anything else, when the first user hits the download link or every time someone downloads the file. You can do this by providing a download link that is interpreted by your web server or web framework as a location of the file, e.g.
http://example.org/uploads/file1.csv
or you write a custom action/page for downloads, like:
http://example.org/download.php?filename=file1.csv (how to make a download link in PHP)
Generate an HTTP response which will be interpreted by the client (the browser) as a download. You won't need to write an extra file to disk, but it's most useful for filetypes, that you can easily generate in your program, e.g. rows of CSV files and the like. Here's an example for CSV files: http://code.stephenmorley.org/php/creating-downloadable-csv-files/
In any way the browser knows, that it deals with a file download and not with just another webpage is through the HTTP headers:
// specify the MIME-type
// (e.g. if it's an image or PDF most browser can display the content directly)
header('Content-Type: text/csv; charset=utf-8');
// The Content-Disposition response-header field has been proposed
// as a means for the origin server to suggest a default filename
// if the user requests that the content is saved to a file.
header('Content-Disposition: attachment; filename=data.csv');
You can read more about that here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
In the end, it's really up to you and your requirements. Is it a low traffic site and and the files are small? - Generate the files beforehand and let the web server deal with the download links. Is it a high traffic site with lot of small files? - maybe generate it on the fly (like in the CSV example). Not everyone should be able to download every file and authentication is managed by your php project? - it will be easier to use a custom download.php script to check permissions.
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)?
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. :)
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.
I am writing a web application in php where users can upload their own files or images, but how can I protect these files from being accessed by others other than the owner. think of dropbox, what is the mechanism to protect those files, I have tried to search but don't get anything about this. any pointers or any link to tutorials would be very useful. thanks in advance.
If you are storing images and files as binary blobs in your database, then it is simply a matter of checking permissions against the logged in user before retrieving and displaying them from the database.
If you are storing them as regular files, what you need to do is store them above the document root of your website, where they are not publicly accessible on the web. Then to retrieve an image, after checking the correct ownership from your database (we don't know your architecture, so substitute however you have stored what belongs to whom), PHP can retrieve the file and send it to the browser with the correct headers.
For example, to display an image:
// Check permissions...
// If permissions OK:
$img = file_get_contents("/path/to/image.jpg");
// Send jpeg headers
header("Content-type: image/jpeg");
// Dump out the image data.
echo $img;
exit();
You can, for example, keep a database table of filenames matched with user IDs to keep track of who owns what.
The typical way to do this goes something like...
A file is uploaded
The file is moved to a directory that is not accessible from the internet
An ID is generated for the file and stored in the database
Then, users use the ID to request the file from the server.
For this purpose, you would have a script that queries the database for the file based on the ID, and would then check if the user has access to reading it. If the user has access, it would read the file and output it to the user's browser.
For example, to read a jpeg image in PHP:
<?php
header('Content-type: image/jpg');
readfile('/path/to/image.jpg');
use unique and special file names, and only present them to the disired user.
you can alsso set a session in PHP and check if the session is correcvt to include a file. and use httacces tio redirect to the PHP.
<?
sessuion_start();
file_exists($_SESSION['specialkey']_$_GET['realfilename']){
include(/* include the file */); // or readfile
//or header location, but then the rteal URL will become visible
}else{
die('acces denied');
}
the specialkey is set in the PHP page making the display page, and is unique for evey file and is gained from DB.
it's the fastest way I could ciomme up with.
you might olso want to store the files in a dir that is only accesable from PHP
edit
instead of include you could use Jani Hartikainen method