When I created my on-line photo album, we had the year 2001 and there was nothing wrong with publishing ones photos in the Internet. It has been almost ten years now, and things have changed. Privacy is an issue, especially when it also affects your friends and family.
So I needed to find some protection. These were my requirements:
This rules out most common options, e.g. protection by a .htpasswd
file. Requirements 3 and 4 point to a solution based on OpenID. With OpenID, my visitors can authenticate against a service they already use (Google, Yahoo, etc.), relieving me from the burden of maintaining a user database and them from having to remember a password.
There is a mod_auth_openid module for the Apache webserver, and it is even distributed with Debian in the libapache2-mod-auth-openid package. So requirement 2 is fulfilled. The tricky part is: How do we achieve OpenID protection for some images, and not for others.
I first played around with selectively enabling or disabling mod_auth_openid based on <FileMatch>
directives in the Apache configuration, but it was not elegant and would not scale well. I have more than 20.000 pictures to manage, and have already selected over 5000 pictures to be shown without protection. My solution is based on a partial copy of the whole directory tree that contains all public files. To save disk space, these are just symbolic links to the real file in the protected location. Some mod_rewrite magic then takes care of giving the user the impression that all files are in the same location. I set up a small example of my solution, which has this directory structure:
.: drwxr-xr-x 2 root root 4096 2. Aug 12:03 images lrwxrwxrwx 1 root root 18 1. Aug 12:05 index.html -> private/index.html lrwxrwxrwx 1 root root 18 1. Aug 12:05 login.html -> private/login.html drwxr-xr-x 3 root root 4096 2. Aug 12:03 private ./images: lrwxrwxrwx 1 root root 33 2. Aug 12:00 pleaselogin.png -> ../private/images/pleaselogin.png lrwxrwxrwx 1 root root 28 2. Aug 12:03 public.png -> ../private/images/public.png ./private: drwxr-xr-x 2 root root 4096 2. Aug 12:00 images -rw-r--r-- 1 root root 267 2. Aug 12:03 index.html -rw-r--r-- 1 root root 94 2. Aug 12:01 loggedin.html -rw-r--r-- 1 root root 2091 2. Aug 12:03 login.html -rw-r--r-- 1 root root 10 18. Nov 2009 protected.html ./private/images: -rw-r--r-- 1 root root 4074 2. Aug 11:58 pleaselogin.png -rw-r--r-- 1 root root 2670 2. Aug 11:58 private.png -rw-r--r-- 1 root root 2043 2. Aug 11:58 public.png
As you can see, real files only reside in private/
, outside of that, only symbolic links exist.
The apache configuration protects the private directory and blends it into the main directory:
<directory /var/www/nomeata.de/openid-test> RewriteEngine On # Abuse the login page as an error image RewriteCond %{QUERY_STRING} \.(png|jpg) RewriteRule ^login.html$ /openid-test/images/pleaselogin.png # Ship private files, if they exist, unless public files exist RewriteCond $1 !^private RewriteCond /var/www/nomeata.de/openid-test/$1 !-f RewriteCond /var/www/nomeata.de/openid-test/private/$1 -f RewriteRule ^(.+)$ /openid-test/private/$1 </directory> <directory /var/www/nomeata.de/openid-test/private> AuthOpenIDEnabled On AuthOpenIDDBLocation /var/lib/apache2/mod_auth_openid/mod_auth_openid.db AuthOpenIDLoginPage /openid-test/login.html AuthOpenIDTrustRoot http://nomeata.de AuthOpenIDCookiePath / AuthOpenIDCookieLifespan 2592000 </directory>
A special trick handles the “login page” for protected images: If the login page is requested and the referrer indicates that the user tried to access a .png
or .jpg
file, apache will instead ship an image containing an error message.
For my photo album I have a small Perl script that, given a directory with a private/
directory therein and a list of rules in form of glob patterns, will symlink matching files and remove symlinks that are not allowed any more.
As you can see, this does not actually protect the content. It only requires the user to authenticate, then everything is visible. To select which OpenIDs are allowed to access which code, some bugs will have to be fixed in mod_auth_openid first. There was little activity there recently, I hope that the project is not dead.
Have something to say? You can post a comment by sending an e-Mail to me at <mail@joachim-breitner.de>, and I will include it here.
http://openid.aliz.es/Oh