Using PHP/Apache to restrict access to static files (html, css, img, etc)

I would consider using a PHP loader to handle authentication and then return the files you need. For example instead of doing <img src='picture.jpg' /> Do something like <img src='load_image.php?image=picture.jpg' />.

Your image loader can verify sessions, check credentials, etc. and then decide whether or not to return the requested file to the browser. This will allow you to store all of your secure files outside of the web accessible root so nobody is going to just WGET them or browse there 'accidentally'.

Just remember to return the right headers in PHP and do something like readfile() in php and that will return the file contents to the browser.

I have used this very setup on several large scale secure website and it works like a charm.

Edit: The system I am currently building uses this method to load Javascript, Images, and Video but CSS we aren't very worried with securing.


X-Sendfile

There's a module for Apache (and other HTTP servers) which lets you tell the HTTP server to serve the file you specify in a header in your php code: So your php script should look like:

// 1) Check access rights code
// 2) If OK, tell Apache to serve the file
header("X-Sendfile: $filename");

2 possible problems:

  1. You need access to rewrite rules (.htaccess enabled or direct access to config files)
  2. You need mod_xsendfile module added to your Apache installed

Here's a good answer in another thread: https://stackoverflow.com/a/3731639/2088061


I have been thinking a lot about the same issue. I am equally unhappy with the PHP engine running for every small resource that is served out. I asked a question in the same vein a few months ago here, though with a different focus.

But I just had an awfully interesting idea that might work.

  • Maintain a directory called /sessions somewhere on your web server.

  • Whenever a user logs in, create an empty text file with the session ID in /sessions. E.g. 123456

  • In your PHP app, serve out images like this: /sessions/123456/images/test.jpg

  • In your htaccess file, have two redirect commands.

  • One that translates /sessions/123456/images/test.jpg into /sessions/123456?filename=images/test.jpg

  • A second one that catches any calls to //sessions/(.*) and checks whether the specified file exists using the -f flag. If /sessions/123456 doesn't exist, it means the user has logged out or their session has expired. In that case, Apache sends a 403 or redirects to an error page - the resource is no longer available.

That way, we have quasi-session authentication in mod_rewrite doing just one "file exists" check!

I don't have enough routine to build the mod_rewrite statements on the fly, but they should be easy enough to write. (I'm looking hopefully in your direction @Gumbo :)

Notes and caveats:

  • Expired session files would have to be deleted quickly using a cron job, unless it's possible to check for a file's mtime in .htaccess (which may well be possible).

  • The image / resource is available to any client as long as the session exists, so no 100% protection. You could maybe work around this by adding the client IP into the equation (= the file name you create) and do an additional check for %{REMOTE_ADDR}. This is advanced .htaccess mastery but I'm quite sure it's doable.

  • Resource URLs are not static, and have to be retrieved every time on log-in, so no caching.

I'm very interested in feedback on this, any shortfalls or impossibilities I may have overlooked, and any successful implementations (I don't have the time right now to set up a test myself).


Create a rewrite map that verifies the user's credentials and either redirects them to the appropriate resource or to an "access denied" page.