Reputation: 3028
I'm creating files based on user data (taking from the database table, writing to a csv file, storing on the server, and then printing out a link for the user (logged in) to download).
how can I ensure that only the user can download that file? For instance, if the file is stored at http://mysite.com/username/file, how can I make sure only that user, when signed in, is the only one who can download the file? Using php.
thanks for the help
Upvotes: 0
Views: 1684
Reputation: 751
The PHP manual has a user submitted entry that does what you're looking for:
function query_to_csv($db_conn, $query, $filename, $attachment = false, $headers = true) {
if($attachment) {
// send response headers to the browser
header( 'Content-Type: text/csv' );
header( 'Content-Disposition: attachment;filename='.$filename);
$fp = fopen('php://output', 'w');
} else {
$fp = fopen($filename, 'w');
}
$result = mysql_query($query, $db_conn) or die( mysql_error( $db_conn ) );
if($headers) {
// output header row (if at least one row exists)
$row = mysql_fetch_assoc($result);
if($row) {
fputcsv($fp, array_keys($row));
// reset pointer back to beginning
mysql_data_seek($result, 0);
}
}
while($row = mysql_fetch_assoc($result)) {
fputcsv($fp, $row);
}
fclose($fp);
}
// Using the function
$sql = "SELECT * FROM table";
// $db_conn should be a valid db handle
// output as an attachment
query_to_csv($db_conn, $sql, "test.csv", true);
// output to file system
query_to_csv($db_conn, $sql, "test.csv", false);
Upvotes: 2
Reputation: 4520
Sounds like a trivial question... there's any number of ways, if the user is logged in then simply check the file they're requesting belongs to them.
The best way to do this would probably be to use a pass-through file. For example the request to /username/file
would actually be calling /download.php?id=username&dl=file
in which you can then checked the logged in user is equal to id or the username of the file trying to be downloaded from and if they match then use php header location to redirect the request to another location although that can be exploited by looking at headers; so to make it seemless, you'd store the files outside the web directory and read in the file using php and output it directly to the browser.
Upvotes: 0
Reputation: 4121
You could make a file called download.php
, for example:
if($logged_in && $username == $_GET['download_username']) {
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=nameofdownload.zip');
readfile('downloads/' . $_GET['download_username'] . '/file.zip');
}
Then in the downloads
folder, you could create a .htaccess
file, and put the following:
Deny from all
Upvotes: 1
Reputation: 385
Unfortunatley you will need to wrap the download in some code. You can use a technique similar to this:
if ($user->is_correct_user_with_access())
{
header('Content-Type: application/octet-stream'); // this can be replaced with whatever file format you want;
echo file_get_contents($local_path_to_file);
die;
}
Also ensure that the file you are generating is not in a path that is publicly accessible (ie, it should be below your document root)
Upvotes: 0
Reputation: 37701
If the user is not logged in, or if it's a wrong user, just show a message or redirect or whatever you want instead of giving access to the file. And that url example you've shown should be only a page with a link or redirection to a real file. You can even generate a file name hashes for even better security.
Upvotes: 0
Reputation: 40150
I was about to edit your question and remove the sql and csv tags because, as asked, it doesn't really have to do with those topics. However, my answer does.
Instead of saving a file to the file system, just generate the csv file for output directly to the response. Your code would only generate the correct csv for the user (or no content for non users), thereby solving the problem.
This assumes generation of the file is modestly lightweight and would not be done very frequently.
Upvotes: 1