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)."'";
$开发者_JAVA技巧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:
- The RewriteMap statement needs to be defined inside the virtual host block if you are going to use it inside that virtual host. Placing it outside of the block will not work.
- You must have set RewriteEngine on before defining the RewriteMap or it will be ignored.
- RewriteLock cannot be in the virtual host block.
- As with any shell script, the php file must be executable by the apache user and void of ^M's
- RewriteMap statements cannot be placed in .htaccess but the other statements that use the map can.
RewriteCond %{HTTP_COOKIE} !mysessioncookie=([^;]+)
RewriteRule .+\.(jpg|css|js) forbidden.html [R=403]
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.
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.
精彩评论