简体   繁体   中英

protect files via .htaccess and PHP

Might have been discussed before, but I just can't find a quick and clean solution.

1) I have a bunch of files in my /data/ folder: .jpg, .gif, .mp4, .pdf, etc.

2) I want to create a /data/.htaccess file that will catch each request and redirect it to a PHP processor, eg:

/data/filename.jpg -> /data/processor.php?file=filename.jpg

3) the processor.php will do as follows:

3a) Check if you have a valid $_SESSION['logged_in'] == TRUE

3b) Send corresponding headers

3c) Send file data

Ideally the .htaccess redirect won't change the browser's URL, so all the current file requests will stay valid AS LONG AS you are logged in.

EDIT:

As it was suggested the better approach would be to keep my files outside of the web root. Thus, I'm going to only leave /html/data/processor.php and move all media files (like .jpg and .mp4) to /media/ outside of web root.

If you don't want to change the URL in the browser, then what you want is a URL rewrite instead of a redirect. You .htaccess file should look something like this:

RewriteEngine On
RewriteRule ^data/(.+) /data/processor.php?file=$1 [L]

This will cause requests to /data/filename.jpg to actually request /data/processor.php?file=filename.jpg without doing anything to the URL in the browser. Then your processor.php script can take over from there.

Keep in mind that you must have mod_rewrite enabled within server's configuration.

Something else to consider. You may or may not want to keep these files outside of the document root depending on which is more important: security or usability. If the ,htaccess portion fails for whatever reason, do you want the files to by default be accessible or not? In other words, do you give the user the benefit for the doubt as to their access rights in this case? If so, leaving the files where they are would be best as the URLs will just work and deliver the files the user is expecting. If you want to error on the side of not granting access, then moving the files outside of document root would be good so that they are not accessible without the mod_rewrite rules going through your script.

/data/processor.php

Here is a sample of what your processor could look like:

<?php
// Get MIME Type
    $finfo     = finfo_open( FILEINFO_MIME_TYPE );
    $mime_type = finfo_file( $finfo, $_GET['file'] );
    finfo_close( $finfo );

// Send headers
    header( "Content-Type: $mime_type" );
    header( "Content-Length: " . filesize( $_GET['file'] );

// Send file data
    readfile( $_GET['file'] );
?>

Be sure to include a path along with $_GET['file'] if necessary depending on where you end up locating your files.

Here is the full solution that worked out for me. Just in case it might be useful for anyone. Thank you @Nick Coons!

HTAccess file /html/media/.htaccess

RewriteEngine On

RewriteCond %{REQUEST_URI} \.(png|jpe?g)$ [NC]
RewriteRule ^(.+) index.php?file=$1 [L]

Processor file /html/media/index.php

<?php

require_once '../config/config.php';

// must be logged in
if ( ! @$_SESSION['logged_in']) exit('Access denied. You are not logged in.');

// check if file exists
$file = dirname(dirname(getcwd())) . '/media/' . @$_GET['file'];
if ( ! is_file($file)) exit('404');

// Get MIME Type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file);
finfo_close($finfo);

// Send headers
header("Content-Type: $mime_type");
header('Content-Length: ' . filesize($file));

// Send file data
readfile($file);

/* End of file */

Media folder /media/

.png and .jpg files are stored here outside of the web-root

Now request to /html/media/bike.png only works for logged in users.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM