There is a fully running PHP site that can only be accessed when logged in with ID/password.
I have been asked to add a function to the site that uploads PDF files and show existing PDF files in the browser.
So I achieved this by using iframe to embed PDF files in the browser.
But the problem is, the PDF files shouldn't be directly accessible (shouldn't be opened when accessing www.aaa.com/pdf/test.pdf), and must only be shown in the site so that only authorized users can view the file.
So I tried a few things :
.htaccess : I'm not too familiar with PHP/HTML so searched some answers on stackoverflow and tried them without success.
such as
order deny,allow
deny from all
allow from 127.0.0.1
or
Require local
and so on. It obviously blocked direct access, but also didn't allow the PDF to be shown from the site (www.aaa.com/showPDF.php). Come to think of it, the above methods seem to only allow the files to be read when opened from the physical server.
Moving the PDF folder outside of webroot : I succeeded moving the upload folder outside of webroot and also uploading to it, but then iframe doesn't work since PHP can't find the PDF file. A workaround was to use headers and PHP readfile(), but I can't seem to modify the headers from where I'm from since the headers are already sent beforehand in files that I cannot modify.
I think I'm making this overly complicated, and I think an appropriate .htaccess file will simply do, but don't have much knowledge in this area. Would really appreciate help here, thanks!
Seems it was simple enough.
Order Deny,Allow
Deny from all
Allow from www.aaa.com
worked. Thank you for your suggestions!
=======================================
Edit : above didn't work.
In fact, I didn't have permission to access outside my webroot.
So I stored the pdf files inside a folder within my webroot and denied access from all by using :
Deny from all
in .htaccess.
After that, since iframe was denied by .htaccess, I tried to print the contents of the PDF by using file_get_contents(). But this required setting header information such as
$contents = file_get_contents($filePath);
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
echo $contents;
But the php page that shows the contents of the PDF file (showPDF.php) already sent out headers during initializing, and I didn't have rights to modify that part.
So I made a fresh php file (pdfviewer.php), added session information, and added the above 4 lines. After that I iframed pdfviewer.php within showPDF.php and it finally worked.
I think this problem was REALLY specific to my current situation but hope someone finds it useful.
Also, thanks #CBroe since I realized I was wrong and got some hints!
Related
Here is the current scenario:
I have an index.php file located at ./dl/ that lists the files in a folder named ./dl-meta/, using the glob function. It works pretty well.
The thing is, I would also like to password protect my files. I took a look at Apache's folder protect utilities, tho upon further inspection I realized that someone could easily brute force their way into my files. (I also saw that the password menu looked quite bad). So, instead of using Apache's rules, I tried making my own folder protect script in PHP, using session variables.
...The login script I crafted does a great job protecting my PHP files. Once the session is started, I can simply call this bit of code at the start of my PHP pages located at /dl-meta/ to see if the user has the right to view the page:
if($_SESSION['login'] === false){
echo "Access denied :(";
die();
}
Obviously, I can't run this piece of code for files like video.mp4 (AKA I can't deny access to video.mp4 if the user is not logged in).
Is there some way I can deny access for non-PHP files when the user is not logged in?
or maybe...
Should I obfuscate the /dl-meta/ folder? If so, how could I achieve this without breaking my file indexer and /dl-meta/'s folder hierarchy? Keep in mind that there are multiple subfolders in there...
Thanks for the read, SO! Feel free to ask for my code if you think it can help.
I figured it out...
Using readfile(); I can make it so im able to download a specific file, from another location. Heres an example:
$path = "./files/video.mp4";
header('Content-Type: ' . mime_content_type($path)); //Tell the browser to interpret as an .mp4 file
header('Content-Disposition: inline; filename="'.basename($path).'"'); //Change name of file (cool if you want to add some kind of watermark to your filenames)
readfile("../dl-meta/".$path); //Distribute the damn thing
Using the above code will make the client download the file/play it like if you directly accessed the resource. AKA you can download files from /script/file.php without revealing the URL of the actual file.
My goal is accomplished: I can protect files like video.mp4 behind a hand made PHP login wall.
Tho, some questions still remain unanswered.. Will this code make the downloads slower/use more system resources than vanilla direct downloading?
Bigger 5gb 2 hour MP4 files dont even load anymore... Any tips with that please?
This question already has answers here:
How to password protect streaming videos with php
(4 answers)
Closed 4 years ago.
I have an interesting dilemma... I am hosting several .mp4 files on a WAMP server. I am well aware of the method of storing files outside of the document root and using a PHP script to authenticate a user before retrieving the file contents. However, these .mp4 files are required to be inside the document root. Is there any way that I can authenticate a user who is trying to directly access one of these files? I have tried a .htaccess rewrite that takes a requested URL ending in ".mp4" and redirects to a PHP script passing the requested file as a parameter, but of course this just loops.
This is the rewrite rule in the .htaccess file...
RewriteEngine on
RewriteRule ^(.*).mp4$ /media/auth.php?file=$1.mp4
The idea was, a user will try to access http://www.example.com/media/myVideo.mp4, this reuest would get routed to a PHP script (auth.php) that would pick up the requested file from the URL using $_GET['file'], it would authenticate the user using a $_SESSION variable, and then user a header('Location: ' . $file) to send the authenticated user to the actual file. Again, I realized quickly after implementing this that it would just loop...
Any help would be greatly appreciated. Thanks!
Here's why they cannot be outside the doc root...
#IdontDownVote, very complicated, but I'll attempt a short version... I have this MOSTLY working great with files outside the doc root, with one serious issue. When I access the files using the PHP script, I am able to view the video in the Chrome browser, play, pause, rewind, the whole deal. The only (big) problem is when I use this method, I am not able to Cast the video. When I access a .mp4 file directly, it gives me the option to Download or Cast, but using the PHP script, only the Download option is available. Believe me, I have tried everything including discussing with two Google developers. I posted on Stack Overflow about this issue here with no joy...
Why can't I cast an MP4 file served by PHP from outside of the document root?
I am not sure why this is getting downvoted, this is causing my a lot of headache and I am just looking for advice...
First off have you tested it when serving the file though PHP outside of the document root?
When I access a .mp4 file directly, it gives me the option to Download or Cast, but using the PHP script
If you can then you can simply block access to all but one PHP file and use that to dish it out (you could allow access to *.php too..
#.htaccess
Order Deny,Allow
Deny from all
<Files index.php>
Allow from all
</Files>
That will only allow index.php to be accessed in whatever folder (and sub-folders) the htacccese is put in. This might be better if you have a existing login system in PHP that you want to make use of for your users.
If you can't then the only way I can thing of is to try using BasicAuth, and Htaccess like this:
#.htaccess
Order Deny,Allow
Deny from all
AuthType Basic
AuthName "Admin Only"
AuthUserFile /pathto/.htpasswrd
require valid-user
Allow from all
Then in a file named .htpasswrd put some stuff like this:
admin:$apr1$o48wfurr$5WaWCjD85kBu/ydGKsQeq/
You can use something like this to hash the password.
http://www.htaccesstools.com/htpasswd-generator/
Then when you give Chrome the url, you'll have to include the user:pass# part to bypass the login.
http://user:pass#somedomain/path/to/video.mp4
If you wan't to tie this into an existing login, you'll have to create some system to sync the passwords in the htpasswrd file to those of your users. That really shouldn't be too hard. I made one to sync our site users accounts to sFTP server, that was a real pain because of security and we have 3 sFTP servers (legacy, normal and dev). Anyway you just basically have to keep a list of their user/password and then update the file when a user is created/deleted or changes their password.
Maybe it will work (I honestly don't know ... lol).
Worth a shot.
I'm having trouble putting data in safe locations. What I want to do is allow my localhost to access the files to create my pages but prohibit all other access.
I started out trying to write a .htaccess file to prevent access to subfolders but read here that this was a poor way to do things and was getting into a tangle anyway so, following advice, I tried moving the files out of the public_html directory:
The structure is:
bits_folder
images
testimage.jpg
files
testfile.php
public_html
application
callingfile.php
With this layout, I get error 404 if I try to access anything in bits_folder from the browser, as desired. callingfile.php however does not seem able to access the testimage, but can include the php testfile.
callingfile.php:
require("../../bits_folder/files/testfile.php"); //works and displays file echo
<img src="../../bits_folder/images/testimage.jpg" //gives broken image
both the files (testimage and testfile) are in the folders where they should be.
I am assuming that the reason for this behaviour is that the img is a http request after the page is served and will thus be denied but I am no server expert. Is this the case? Can this be overcome? Should I be doing this another way?
Only place scripts and images for PHP to use outside public_html. Images and other things that are as src or otherwise linked in HTML/JavaScript cause the browser to request those. The web server will refuse to serve them from outside the public directory.
Your browser will get access denied for www.example.com/../../bits_folder/images/testimage.jpg
Trying to protect video files that are done in camtsia which outputs html/with flash embed video files.
Not sure how I would access them using PHP. I've searched stackoverflow and found using alias would be an option? Is that still secure though? Is that the best way to go? Or should I try to purue a file open operations using PHP.
It needs to serve an html page which has .js .swf files along in the same protected dir.
Any help or direction is appreciated.
You would use readfile to access the file and the header function to forge the content. Make sure the www-data user, which is the Apache user and PHP uses it to access the filsystem, has permission on that folder.
header('Content-type: video/avi');
header('Content-Disposition: attachment; filename="videodownload.avi"');
readfile('/var/videos/myvideo.avi');
I have an application that let users to upload files to server. All files are stored in one directory called Uploaded Files (which has Thumbnails directory inside).
What are the most common ways for preventing users to see these files ? I mean I don't want users to see the files by typing URL like /path_to_website/Uploaded Files/1.png.
On the other side, authorized users should be able to see the files by getting a page that contains paths to files, like: ../Uploaded Files/1.JPG, ../Uploaded Files/2.png, ../Uploaded Files/3.gif. These users should be able to see only the files that appear on the page they got, i.e. I want to prevent them to see ../Uploaded Files/823.gif for example.
Please help to understand how this kind of things are done these days.
Thanks a lot !!
You can move the images into a folder out side the public directory and then stream them in via PHP to the users who are allowed to view them. By using the method detailed in the PHP header() manual for a very basic output (see Example 1).
Otherwise you could put a .htaccess file in the folder containing:
deny from all
if you are running Apache, but you still need to stream it out through PHP.