Solved

Protect files from being download unless logged in

Posted on 2009-05-06
18
465 Views
Last Modified: 2013-11-16
I have a page that can only be accessed by users who are logged in. On this page are links to pdf files. The problem I have is that while the page is secure the actual files are not. A user can type in the url to the file and download the PDFs without being logged in. One option I know is to protect the directory however this will prompt the user to enter another login. Another option I thought of is to place the files in a directory not viewable by the web such as where I may have

http/www/

and www is where the site lives. Can I place the files here:

http/downloads.

If that is the case I am not sure how I can access the files from http/downloads

Is there a better way to accomplish this?
0
Comment
Question by:SaltyDawg
  • 10
  • 5
  • 2
  • +1
18 Comments
 
LVL 34

Accepted Solution

by:
gr8gonzo earned 250 total points
ID: 24314997
Hi Salty,

For your situation, it's much better to place the files into a directory not viewable from the web. Since PHP usually has the ability to access any file on the server (as long as it has permission), you can have a PHP file that people go to when they want to view the PDF file. PHP then checks to see if they are logged in, and if they are not, it can send them to the login screen. Otherwise, the PHP can go and suck in the file data of the PDF and send it back to the user.

There's one simple function call to tell PHP to get all the file data and show it all to the browser:
<?
readfile("/the/system/path/to/the/file.pdf");
?>

So if your PHP script was http/www/pdfviewer.php and your PDF file was http/downloads/secret.pdf, then pdfviewer.php  might look like this:
<?
// Check to see if they are logged in
session_start();
if(.... logic here to check to see if they are logged in ...)
{
    // Show PDF
    readfile("../downloads/secret.pdf");
}
else
{
   // Redirect to login
   header("Location: LOGIN_URL_GOES_HERE");
}
?>

There are also special header parameters you can add later if you run into problems with browsers viewing the file, or if you want to prompt the user to download the file instead of viewing it inside their browser. The header() function is responsible for telling the browser how to handle the file data you're sending it with readfile().

If you DO need to use header() to tell the browser how to handle the data, you may want to look at the PHP documentation for that function. There are tons of examples that people have posted in the comments on how to show or download files.

http://us2.php.net/function.readfile
http://us2.php.net/manual/en/function.header.php
0
 
LVL 10

Expert Comment

by:webwyzsystems
ID: 24315298
I think you would be best to read up on, then implement HTACCESS.
This is a tried and true method to accomplish exactly what you are attempting. Since you are on Apache, everything is all ready to go.
Here's a pretty good link - read it and you should be able to complete what you want in an hour or less.
http://www.javascriptkit.com/howto/htaccess.shtml
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24315365
using this method
readfile("../downloads/secret.pdf");

causes the browswer to open and read the file, displaying the binary data for the pdf..

How do I get the header file to work and prompt for download?

Also along with PDFs, Doc and XLS files may be there.
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24315402
But doesn't HTACCESS prompt the user for a login
0
 
LVL 7

Expert Comment

by:ycTIN
ID: 24316486
* remember storage the files at secure area

<?php

	/*

		check the user access right here

		if the user is not allowed to access the file, redirect to other page

	*/
 

	//download file (file path, file name)

	downloadFile("test.pdf","test.pdf");
 

	public static function downloadFile($file,$filename){

		$b = get_browser(null, true);

		if ($b['browser'] === "IE") {

	 		$filename = urlencode($filename);		

		}		

		if(file_exists($file)) {

	        header('Content-Description: File Transfer');

	        header('Content-Type: application/octet-stream');

	        header('Content-Disposition: attachment; filename="'.$filename.'"');

	        header('Content-Transfer-Encoding: binary');

	        header('Expires: 0');

	        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

	        header('Pragma: public');

	        header('Content-Length: ' . filesize($file));

	        @ flush();

	        readfile($file);

	        exit;

	    }

	}

?>

Open in new window

0
 
LVL 10

Expert Comment

by:webwyzsystems
ID: 24316783
htaccess will prompt for login if the user is not authenticated. If the user is authenticated - everything is good. I suppose it depends on how many users you are talking about, and how your system has to scale up. HTACCESS is suited for systems that will be growing beyond 10 users. Once implemented, you don't have the overhead of checking user access on every page. The authentication header is just passed along.

There is risk in all file download handling scripts in that they are usually passed a parameter to indicate what file is to be downloaded. You need to be very careful with your coding...or saavy folks will be downloading whatever they want from your server.

How are you currently authenticating users?
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24317144
while HTACCESS does protect the files, it also prompts the user for authentication which is something I don't need. The user login before they can enter that section of the site, so I do not want to prompt them again for a different login. Don't want the customers to do anything that may be redundant.
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24318617
ok I did the following below code and got this.

%PDF-1.4 %âãÏÓ 45 0 obj <> endobj xref 45 36 0000000016 00000 n 0000001461 00000 n 0000001541 00000 n 0000001670 00000 n 0000001910 00000 n 0000002330 00000 n 0000002551 00000 n 0000002836 00000 n 0000002912 00000 n 0000002986 00000 n 0000005105 00000 n 0000005705 00000 n 0000006111 00000 n 0000006774 00000 n 0000006808 00000 n 0000007088 00000 n 0000007371 00000 n 0000007882 00000 n 0000008099 00000 n 0000008400 00000 n 0000008482 00000 n 0000008888 00000 n 0000009284 00000 n 0000009566 00000 n 0000009850 00000 n 0000036009 00000 n 0000038678 00000 n 0000052912 00000 n 0000072194 00000 n 0000082650 00000 n 0000094979 00000 n 0000106173 00000 n 0000227454 00000 n 0000243142 00000 n 0000252789 00000 n 0000001016 00000 n trailer <<5A09A0F78B50814F80D5B79B0E6D008A>]>> startxref 0 %%EOF 80 0 obj<>stream xÚb```"VÆÈu B  cÊr¼`Ü 0ߢi O¡îrþG*`s®¿ÍýÀ¬ ÜÎ(<¾à²ÐmZ"ÉT¡P9ä.×é0Óf8´Jâ³eñÒu"ê:z#u; G`Hå¢+~!×bÛ¢ ú¬²"Ig.&x <: T³ì}H"ÅACÜ`£N²ªRÊ=Ì!Üï(Ô±Ù3P5¸Kl>£ Æ¥¥wtt¬]âa `¹4 @: ZRM\ÁZ & `¬¹ ýè~jTdà¿ê ¦4Àö)12è778po`¿Á°!¬C"Qa!Áoûæ'Ì»¶3´6ð0è5Æ-`?ÀüâR·ô¡3¬b! c}§ÕTù¨ö2Ô3D2H>àu`ã`}Ã80Ѳ üw{@! ÄÖ@¬ÃÀÿÆH3ñ-¬7yË endstream endobj 46 0 obj<> endobj 47 0 obj<> endobj 48 0 obj<>/ColorSpace<>/Font<>/ProcSet[/PDF/Text/ImageC]/ExtGState<>>> endobj 49 0 obj<> endobj 50 0 obj<> endobj 51 0 obj<> endobj 52 0 obj<> endobj 53 0 obj<> endobj 54 0 obj<>stream H0¬WÛrÛ6}çW /©3¢q¿ô-0ÝL:Ó4êô!éCÑ6[]lR²ë·|Q¿± QtI'ãH9ÝÅ9gwA5Ê8΍ÔHcÃ9-4Á¨©2R¡hý¶ý÷3$ E »ö®³³ï(ºn;_1*rCDç}HÄ¥Ì <ýUö6»ë·¥:çv[ØIp[! ®y}ugùÇàú[C’°Æ ë.Så K¥Âð+"S¥´aƱ\jR o1ÚGF@ó5Û]'F×)ÆÔçH0ÏîÇĨ{:û0ô"'´#|hÄI8¥TO0xgö)~ÖÍ'w29AÆÞ"ôÌnü{ÛEDãwI®5°0ºí¶äqR6ÍP°¦_aÔ’wÓ/hBy\S:vz^°Â1xt<¶Ù»­"Öý¥Ú:<Æ"LSà;pW¢~îá'WÐôô&©ìBÜnáàKd¾"îq²)AÔ(ì^sÄqÜËÐ*zmÖÇСÔä6}±Óe{ö¢"èÅ;D:Ëw/.û"²u+m¹õ"fûL¢_c±jkÊbeªüʷ¤þå~ÔZä(|èwR’ôØø"0°ßuÜSaÌûYQ7ó£9]­wsÂàËÚTE{hêí5j÷žÞm[tÛÌ0Î $Qðq_¯ªú8'çx ö7ÕüÏåÏÙÜ=[Sbè~õûÙÇC½^Y!~mÕ }ÿúξ޽K}§SP:fFõÝ°t\}H4â’a#ɮҷ¼&WpDÈé)&¢ßÆ:ցs, Þ ÉAĹ'¶c:Þî£g0Y¤×6½Í¸æx­UW*ùDìƱÉAõ ’~°I(R¹BW`°ÛÕ%(º1w]’!TCÂùàlÑGÉ3åß `!¦ý"r¿{Ü5Õ2.P½]ÕÐ:Å: ®`\Æj:x %}c5Ǭ/&P¥H0áõVÊ ¦Ñ§T7ï*¨®<® ÐǼ⩍gÆñPx¨/8Ý"¿·MÓ6à aæf®s=»­abhª󤡾®Kß²ÛÝÕ|AØî»6Û_@%âSæ ’^2Jr&A\û!Zí¿]QÂ8ÁÄ ÒÇ`o8|m ßÏ.þé÷+«uê ©ÄïÈ¥æ¹Á,õ9;´0$XC:¹"ÅcDT~Ǿ »C’~=xS<{ ¬¬ÛçmÕWè!a)L. ÇóÄÜA°

(...plus more)

it seems to open the file but doesn't know how to open it. Anyone know what I can do now?
	$filename = "../media/downloads/pdf/2006_BackDrop.pdf";

	header('Content-Description: File Transfer');

	header('Content-Type: application/pdf');

	header('Content-Disposition: attachment; filename="'.$filename.'"');

	header('Content-Transfer-Encoding: binary');

	header('Expires: 0');

	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

	header('Pragma: public');

	@ flush();

	readfile($file);

	exit;

Open in new window

0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24318629

	$filename = "2006_BackDrop.pdf";

	$filename = "../media/downloads/pdf/2006_BackDrop.pdf";

	header('Content-Description: File Transfer');

	header('Content-Type: application/pdf');

	header('Content-Disposition: attachment; filename="'.$filename.'"');

	header('Content-Transfer-Encoding: binary');

	header('Expires: 0');

	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

	header('Pragma: public');

	@ flush();

	readfile($file);

	exit;

Open in new window

0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 1

Author Comment

by:SaltyDawg
ID: 24318647
miscopied again
	$filename = "2006_BackDrop.pdf";

	$file = "../media/downloads/pdf/2006_BackDrop.pdf";

	header('Content-Description: File Transfer');

	header('Content-Type: application/pdf');

	header('Content-Disposition: attachment; filename="'.$filename.'"');

	header('Content-Transfer-Encoding: binary');

	header('Expires: 0');

	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

	header('Pragma: public');

	//@ flush();

	readfile($file);

	exit;

Open in new window

0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24318990
ok does anyone know any script to make downloads automatically pop up from a redirection like on download.cnet.com? Also can someone confirm that doing it this way will actually hide the directory the files are actually on?

Let me add the I am not trying to make it that secure. If a savvy individual is able to find the directory, its not a real problem. My goal is just to make it where a person cannot go directly to the file and by file the page links.

if I can do it this way I have already thought of a script to move the directory location periodically
0
 
LVL 7

Expert Comment

by:ycTIN
ID: 24323678
create file file.php for download


<iframe id="iFile" src="blank.html" style="display:none;"></iframe>
on user click the donwload link change the iframe url to file.php (e.g. file.php?id=123456)
0
 
LVL 7

Expert Comment

by:ycTIN
ID: 24323706
the code working fine with me, or you can try following header
and check you source code file do you have are invisible char before header()
header("Pragma: public");

header("Expires: 0");

header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

header("Content-Type: application/force-download");

header("Content-Type: application/download");

header("Content-Disposition: attachment;filename=$filename ");

header("Content-Transfer-Encoding: binary ");

Open in new window

0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24327524
we I use the header code I can open certain files expect application files. The browser opens the file within the browser screen and only shows the binary for that file. Like what I have shown above this is what I get when I use a pdf and the same with a .doc and .xls file.
0
 
LVL 7

Assisted Solution

by:ycTIN
ycTIN earned 250 total points
ID: 24327927
I created the demo for this function, and tested in FF/IE , linux/ Windows Server

Demo
http://demo.yctin.com/php-func-readfile/

Download Demo
http://demo.yctin.com/php-func-readfile/php-func-readfile.zip
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24327990
Hello ycTIN
I think this is what I am looking for. Is this using the example you have above? How is it set up?

Thanks
0
 
LVL 7

Expert Comment

by:ycTIN
ID: 24328155
the code working in webserver default setting
you unzip the demo to your webserver still have same problem?
0
 
LVL 1

Author Comment

by:SaltyDawg
ID: 24328998
ycTIN & gr8gonzo
Ok I think I may have had some browser setting issues that cause problems with the download. I changed my setting and now your header functions are working. So I will continue to test this out and make sure I do have it right.

Thanks
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now