Solved

Protect files from being download unless logged in

Posted on 2009-05-06
18
499 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
Simplifying Server Workload Migrations

This use case outlines the migration challenges that organizations face and how the Acronis AnyData Engine supports physical-to-physical (P2P), physical-to-virtual (P2V), virtual to physical (V2P), and cross-virtual (V2V) migration scenarios to address these challenges.

 
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
 
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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I imagine that there are some, like me, who require a way of getting currency exchange rates for implementation in web project from time to time, so I thought I would share a solution that I have developed for this purpose. It turns out that Yaho…
If you are a web developer, you would be aware of the <iframe> tag in HTML. The <iframe> stands for inline frame and is used to embed another document within the current HTML document. The embedded document could be even another website.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

839 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