Luke
Luke

Reputation: 45

Restrict content access to logged in users with PHP

I have a LAMP setup and I just want to be able to protect content on the webpage (images,css,videos,etc) so that only logged in users can access it.

I realize I can do this easily with .htaccess. However I do not want to use the authentication popup, and I want to be able to use sessions and also be able to logout.

I am using php to do the job of authenticating with mysql and create sessions. This works great. But images, css, javascript etc are still accessible.

How do I allow access to the content only if a valid php session exists?

I have come across using mod_rewrite to forward files to a php file (like auth.php?file=...) and do session checking there. This seems inefficient to check the session for every single image in a page that has already been checked. It seems like a hack and I keep thinking there is a cleaner way of doing this.

Is there a mod for apache like mod_session_cookie that could check if a cookie with a session key exists in my session database and if so sets Allow from all for the directory?

Alternatively, is it possible to use mod_auth_mysql but also be able to use sessions and login using a php form and not the authentication popup?

EDIT:

Here is my solution to the problem:

In my apache configuration file (not .htaccess) I added:

RewriteLock /var/www/lib/rewrite.lock

<VirtualHost>
    #...
    RewriteEngine on
    RewriteMap sessionValid prg:/var/www/lib/allow.php

    <Directory /var/www/client/*>
            RewriteEngine on

            RewriteCond %{HTTP_COOKIE} !client-cookie=([^;]+)
            RewriteRule .* - [L,R=403]

            RewriteCond %{HTTP_COOKIE} client-cookie=([^;]+)
            RewriteCond ${sessionValid:%1} !valid
            RewriteRule .* - [L,R=403]
    </Directory>
</VirtualHost>

And the script allow.php:

#!/usr/bin/php5
<?php
set_time_limit(0);

echo ""; 
$stdin = fopen("php://stdin","r");
$db = mysql_connect(...);  
mysql_select_db(..., $db);
$querypre = "SELECT ID FROM Sessions WHERE ID='";

while (1) {
  $line = trim(fgets($stdin));

  $query = $querypre.mysql_real_escape_string($line)."'";
  $result = mysql_query($query);

  if (mysql_num_rows($result) > 0)
    echo("valid\n");
  else
    echo("0\n");
}

mysql_close($db);
?>

This works like a charm. Using this and session_set_save_handler I was able to use php sessions backed by mysql to secure both the php pages and all content within. I hope someone finds this useful.

Some caveats:

Upvotes: 8

Views: 5153

Answers (3)

Brock Batsell
Brock Batsell

Reputation: 5803

I actually don't use Apache; I use lighttpd, which includes a plug-in that you can use to restrict access to a folder based on if a correct hash is passed in the URI. Basically, your application logic and the webserver share a secret salt that is then used to generate a hash with the current time, which is also passed with the hash. If the time is within the past 5 minutes, then it grants access. If not, or if the hash is invalid, then it doesn't. I'm googling around to see if there's a similar plugin for Apache at the moment.

Edit: mod_auth_token appears to do the same thing for Apache.

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798606

RewriteCond %{HTTP_COOKIE} !mysessioncookie=([^;]+)
RewriteRule .+\.(jpg|css|js) forbidden.html [R=403]

Upvotes: 5

alex
alex

Reputation: 490203

Instead of linking straight to the resources, use some form of controller to serve the images.

For example, linking to 'images/bob.jpg' wouldn't actually point to a resource, but a script, which checks login, and if successful, sends image/jpeg headers with the correct data.

Upvotes: 0

Related Questions