Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Echo/print a jpg-image with php, for safety?

Tags:

php

image

Because of safety (check if user are logged in), I call a php-document when showing images.

<html>...
<img src="showImage.php?id=455" />
...</html>


showImage.php:
<?php...

if($_SESSION['user']){
    //Get the src to the image
    $_GET[$id] = mysql_real_escape_string($_GET['id']); 
    $result = mysql_query("
        SELECT src
        FROM Media 
        WHERE id = '".$_GET['id']."'
        ");
    $data = mysql_fetch_assoc($resultat);

    // Output the image
    header('Content-Type: image/jpeg');
    echo(file_get_contents("media/".$data['src']));
}

...?>

When doing this, I hope the user never will know the direct url to the image, and when trying to show an image, the user has to be logged in.

I'm not sure this is the best way. Is there a more simpler/better way of doing this, and is this safe. When the script is echoing, it's a bit slow.

  • I want the image to be safe (only logged in user should have access to the image)
  • I want the image to be shown as fast as possible

Looking forward for all your expert-tips.

like image 756
Johan Avatar asked Sep 14 '09 16:09

Johan


2 Answers

First of all, instead of reading the file with file_get_contents and, only then, echoing its content, you can use readfile : it will do both operations in one call -- which will probably be fastest and use less memory than :

  • load the full file in memory with file_get_only
  • and, only then, send that content to the outout


Then, if you only want identified to have access to the images, you don't have much of a choice : if you indentification mecanism is based on PHP, you'll have to pass by PHP to restrict access on the file -- which, yes, will be a bit slower than if using Apache directly to serve the content.


Also : here, you say :

I hope the user never will know the direct url to the image

Reading this, I suppose that your images can be accessed directly via Apache, bypassing your PHP script, if someone knows their URL ; security by obscurity is not good.

A better solution, if you don't want your images to be served by Apache would be to put them in a directory from where Apache will not serve anything :

  • either a sub-directory of your document-root, protected by a .htaccess file containing "Deny from all"
  • or a directory that is not under your document-root, and, so, will never be served by Apache.

Either way, this ensure only your scripts can access the files, and not Apache directly -- which means not a user bypassing the script.


Another idea, about the performance problem, might be to indicate the browser that it can cache your images -- at least, if that makes a sense.

For instance, you might be interested by HTTP-headers suchs as "Etag" and/or "Last-Modified".

like image 191
Pascal MARTIN Avatar answered Oct 18 '22 05:10

Pascal MARTIN


Since you require that only logged in users view the image then I would say that you don't really have a choice when it comes to this. You will have to keep doing it like this until your site becomes insanely popular at which point you might be able to figure out a more efficient system for multiple servers using a lower-level access check than PHP (which costs a lot).

<?php

if($_SESSION['user']){

    $result = mysql_query("SELECT src FROM Media WHERE id = '"
    . mysql_real_escape_string($_GET['id']) ."'");

    $data = mysql_fetch_assoc($resultat);

    // Output the image
    header('Content-Type: image/jpeg');
    readfile("media/". $data['src']));
}
like image 29
Xeoncross Avatar answered Oct 18 '22 05:10

Xeoncross