How to restrict image access to logged in users with PHP and .htaccess
Since I run a
Utah wedding photography site, and each user gets their own online wedding gallery, I needed a way to restrict access to the user's photos to only the logged in user. I am running Apache2 and using php, so the solution involved using .htaccess to redirect all JPG requests to a PHP file which checks if the user is authorised or not. If they are not, it prints out a "please log in" JPG image, instead of the requested image.
Where to go from here
You could use PHP's
getimagesize() to determine wether to send a full sized image or a thumbnail of the error message.
.htaccess to redirect requests
Download htaccess
I'm pretty sure that both jpg and JPG aren't needed. I put them in initially while trying to correct a different problem.
Options -Indexes # Don't allow index view of these folders
RewriteEngine on # Enable rewrite
# If the requested filename ends in jpg or jpeg...
RewriteCond %{REQUEST_FILENAME} .*jpeg$|.*jpg$|.*JPEG$|.*JPG$ [NC] # The JPG and jpg versions probably aren't needed
# Then grab the requested URL from the current directory on and stuff in in the $1 variable (first () pair maps to $1)
# Append the $1 variable as part of the query string when processing auth.php
RewriteRule (.*) http://elementsbycaroline.com/me/auth.php?img=$1 [NC,L]
PHP to restrict access
Download auth.php
<?php
ob_start("ob_gzhandler");
if(!strip_tags($_GET['img']) || !isset($_GET['img']) || $_GET['img'] == "" ){
// If they tried to access this file directly, send them elsewhere
header("Location http://yourhomepageORerrorpage.com/index.php");
}
// We keep user authentication in a session, so we'll need access to that
session_start();
$reqpath = strip_tags($_GET['img']); // Use strip_tags to be safer
// User albums are structured like so
// ourURL.com/me/userphotos/<username>/<album>/...
// $reqpath will now have the <username>/<album>/... part
// <username> matches the username stored in the session variable
// so we get a substring from the start of $reqpath to the first /
$foundslash = strpos($reqpath,'/'); // Get the position of the first slash
if($foundslash === FALSE){ // $foundslash could return 0 or other "false" variables, use ===
header("Location http://elementsbycaroline.com/index.php");
}
// Save their username off...
$username = substr($reqpath,0,$foundslash);
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store, no-cache,must-revalidate");
header("Cache-Control: post-check=0, pre-check=0",false);
header("Pragma: no-cache");
header("Content-type: image/jpeg");
// Assume they aren't authorized unless everything lines up
$authed = FALSE;
if($_SESSION['validated'] && $_SESSION['uid'] == $username){
$authed = TRUE; // By requireding validated and uid to be correct
// We prevent loggedin users from seeing other people's
// pictures
}
if($authed){
// If they're authorized, read userphotos/$PATH
// The .htaccess file is in userphotos (since that's the top level we care to protect)
// so the path is relative to that folder. auth.php is up one level to keep photos
// and code as separate as possible
@readfile("userphotos/".strip_tags($_GET['img'])); // Read and send image file
}else{
@readfile("./path/to/jpg/to/use/if/not/authed.jpg");
}
?>