I have a directory on my server that I want the general public to not have access to. (Nothing. No access to php files, images, anything.)
But I want to allow certain users to access this restricted area based on a boolean value in my php.
Is there any way to use PHP to determine whether or not a user can access a directory, similar to the using an htaccess file but with more customized logic?
One of the easiest way is to redirect restricted users to your homepage.
<?php
header( 'Location: http://www.yoursite.com' ) ;
exit;
?>
You can allow access to specific users by setting Boolean value in your DB.
Below solution will work based on your file storage location.
$file = '/file.png'; // set your file location
$userAccess = false;
if (file_exists($file) && $userAccess) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=your_file.png');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
Check this link also.
Hope it will help you :)
So I finally found an answer elsewhere and it involves setting up a PHP file as a sort of proxy in conjunction with htaccess - http://simpletek.raivo.id.lv/restrict-server-files-access-based-on-php-logic/
Related
I have a login system that is fully functional and I keep the user logged in by their ID in a Session Variable $_SESSION['user_id'].
I would like to use that ID to authorise them to view certain files.
I know I can use a MySQL database to store whether they are authorised to see a certain file and then check their ID against the database when it is accessed via a web page, e.g. file.php with a container on the page, however how do I stop someone from finding out what the URL of the file is (e.g. /files/file.pdf) and navigating to that in their browser and viewing it that way?
I know there has to be a way but my knowledge is obviously limited.
Any help would be appreciated.
Thank you
Connor Wyatt
As per OP's request.
Place your files outside the public html area.
$file = "/var/user/you/outside_folder/file.xxx"; type of thing.
"you can use readfile from your script if the user is authorized"
Bansi's suggestion of using readfile is a good method.
As per an example on that page:
$filename = "file.csv";
$filepath = "/path/to/file/" . $filename;
From example #1
<?php
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
where $file = 'monkey.gif'; can be modified to read as:
$file = '/var/user/you/outside_folder/monkey.gif';
Problem:
After download, the file doesn't contain the data.
i.e it become blank.
So please help me for this.
<?php
session_start();
include_once 'oesdb.php';
$id=$_REQUEST['id'];
if(isset($_REQUEST['id']))
{
$sql=executeQuery("SELECT * FROM file where id=$id");
$rows = mysql_fetch_array($sql);
$file =$rows['file'];
header('Content-Description: File Transfer');
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile('uploads/'.$file);
exit;
}
?>
Why not create a HTACCESS file in uploads folder then states
Allow From 127.0.0.1
Deny From All
Then just create a URL, use HTML5's new download feature, do something like this:
click to download
It saves time trying to use PHP to make a download script.
try replacing this:
$file =$rows['file'];
by this:
$file = "uploads/".$rows['file'];
and this:
readfile('uploads/'.$file);
by this
readfile($file);
if still not working put the value returned by the readfile function
IMPORTANT
Please take in consideration the sql injection issues (see comment of Ondřej Mirtes)
The problem is here:
header('Content-Length: ' . filesize($file));
Content-Length receives zero value and browser downloads zero-length file, as you told him. If $file is path relative to upload/, you should do this:
header('Content-Length: ' . filesize('upload/'.$file));
Be sure that filezise() returns correct size and readfile() realy outputs it.
But the other problem is that you mentioned UPLOAD folder and using uploads. They are not same and case is important. Also, may be using relative paths in 'uploads/'.$file is not a good idea, it is better to use absolute path. For example, '/var/www/upload/'.$file.
Hi I am letting users purchase hidden virtual mov.zip files with paypal. I got the transaction part and the storing the details in the database etc... but after the user comes back to the transaction page I want to link them to the zipped file which is in a restricted folder (.htaccess deny from all). how can i grant them access into this directory to download the file for a couple of days. I can't temporarily move the file out of the directory because of its very large size (its a package of hd action effects).
Thank you.
If your hosting allow you to change the PHP setting for the script timeout, you could just stream the file through a PHP script that would check the user access.
For example, the request :
>http://domain.com/download.php?file=be6bc64c94bbc062bcebfb40b4f93304
<?php
session_start();
if (!isset($_GET['file']) header('Location: index.php'); // invalid request
// 1. check user session
...
// 2. get file from hash (use a Db like MySQL
$file = ...;
// 3. check user privilege for the given file
...
// 4. proceed to download
if (file_exists($file)) {
set_time_limit(0);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} else {
// error 404
}
i have some questions on how folders and files permissions work. say i have users directories outside 'protected' as below..
users
-- usera
-- docs
-- userb
-- docs
protected
i do not want user B who does not have the rights, to access anything in user A directories. also, i do not want any person to access the directories directory via url links. basically i just want users to be able to access their own directories, and no one else. how can it be done?
thanks!
I answered a simular question here limiting users to subdirectories which you should be able to adjust to suit your needs, I've copied it here as well.
Download.php
<?php
/** Load your user assumed $user **/
$file = trim($_GET['file']);
/** Sanitize file name here **/
if (true === file_exists('/users/user'.$user->id.'/'.$file)) {
//from http://php.net/manual/en/function.readfile.php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file.'"');
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));
ob_clean();
flush();
readfile($file);
exit;
} else {
throw new Exception('File Not Found');
}
.htaccess To deny all direct file downloads
deny from all
You would then link to the folders by using /download.php?file=filename.ext and it would only download that file from the users directory of the current user.
You'll want to ensure you sanitize the input file name so you're not vulnerable to directory transversal exploits.
Without more info to go on, my suggestion would be to make sure the user directories are above the web root. This will prevent them from being linked to. Then create a PHP script that validates that a user is who they say they are. Once you know the identify of a logged in user, you can use fpassthru() (http://php.net/fpassthru) or similar to deliver the docs to the user.
I have a subdirectory of users that I want to limit each subfolder to that user only.
For example I have /users/user1 where I want to protect the user1 folder so that only user1 can access the files inside.
I tried playing around with an .htaccess and .htpasswd file, but I get prompted to log in a second time even though I have authenticated against a MySQL database.
I'm not sure what to do to basically have the second log in request automatically handled since the user would be authenticated previously.
I can post some code that I have for my .ht files, but I thought that this info could get the ball rolling.
I think that using a php proxy to access the files would be sufficient in this case, something along the lines of:
Download.php
<?php
/** Load your user assumed $user **/
$file = trim($_GET['file']);
/** Sanitize file name here **/
if (true === file_exists('/users/user'.$user->id.'/'.$file)) {
//from http://php.net/manual/en/function.readfile.php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file.'"');
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));
ob_clean();
flush();
readfile($file);
exit;
} else {
throw new Exception('File Not Found');
}
.htaccess To deny all direct file downloads
deny from all
You would then link to the folders by using /download.php?file=filename.ext and it would only download that file from the users directory of the current user.
You'll want to ensure you sanitize the input file name so you're not vulnerable to directory transversal exploits.