Using Protected Images in ExpressionEngine

Aug 03, 2009

Another ExpressionEngine challenge arose recently involving how to serve up images in a template that are harbored in a directory protected with .htaccess. For this particular client I’m working with, EE is managing a vast library of images, and only certain members are allowed to see them. The million dollar question was this: How can we deliver images into a members-only template that are .htaccess protected, and at the same time mask the true path of the images? A kind of two tiered security measure.

First of all, we want the images to be rendered on a template that is only visible to members of group-x. This is done easily within EE from theĀ Template Access Restriction section of the control panel.

Typically, this would be good enough for protecting sensitive text content, but leaves images still at risk. A real jerk could look at the tag <img src="./images/confidential.png" /> and point all his internet buddies to the path, or take some other stuff he shouldn’t have his dirty little fingers on. The biggest hole is the simple <img> tag. So, to be safe we can protect the /images/ director with .htaccess … but now the upstanding citizens of group-x have to authenticate themselves again with credentials outside of EE to view the images. Annoying.

Here’s what we do. As long you’ve got an image library on your server (like GD, or ImageMagik), you can hide the real path to the images, and avoid the separate login box. Instead of an absolute or relative path to the image in the src parameter, just send it to a secret script that creates the image.

<img src="{path=lib/image}confidential.png/" />

This will output something like this when rendered in EE:

<img src="http://www.example.com/lib/image/confidential.png/" />

What’s cool in this case is that the image will generated from within this off-site script; the user cannot know the real location of the image. Better yet, because PHP can access protected directories, the user won’t be prompted to login via .htaccess. And … (yes there’s more) if we created the script as its own template in EE, it can be protected just like the main template so only members of group-x will be able to view it. For outsiders, the image will not be generated. It’s two-tiered protection.

<?php

$image = "{segment_3}";
$url_path = "{segment_4}";

switch ($url_path):

	case "image_bin":
		$path = '../../photos/';
	break;
	case "espionage":
		$path = '../../state/secrets/';
	break;
	default:
		exit();
endswitch;

if (is_file($path . $image)) {
    $f = $path . $image;
} else {
	exit();
}

header('Content-type: image/png');

$im = @ImageCreateFromJPEG ($f) or // Read JPEG Image
$im = @ImageCreateFromPNG ($f) or // or PNG Image
$im = @ImageCreateFromGIF ($f) or // or GIF Image
$im = false; // If image is not JPEG, PNG, or GIF

if (!$im) {
    readfile ($f);
} else {
    @ImagePNG($im);
}

?>

So now, what does this script look like? If you examine the <img> tag above, you’ll see that the file name (in this case confidential.gif) is actually being sent to the script as a URI Segment Variable … not as a relative path. The third segment in the URI is the file name. The segments give a lot of extensibility to this process.

For instance, if there were more than one directory that these images are being pulled from, just slap another segment on that represents the path, without giving it away. So, /confidential.png/image_bin/. In this particular case, I went a step further, and assigned a code name for the directory segment, which is then translated privately from within the script in the switch.

The script takes the info from the URI segments, and spits out an image. It’s that simple.

What’s beautiful is that, through using this method, you can protect sensitive images through both permitting only certain member groups and hiding the true directories. Oh, and you can still use .htaccess. Now it sounds more like three-tiered security. Sheesh.

Keighl

© 2010 Keighl

1.508.265.3032
info@keighl.com