Forum Moderators: phranque
Let me start by saying that I've just stumbled upon this site, and having gotten by 'till now with the documentation on apache.org I must say this is a veritable gold mine. It looks like Santa came early this year!
Now to my question: I'm trying to implement access control on a directory of downloadable files. When I receive a request for foo.zip, I rewrite the URL to checkaccess.php which checks to see if the user is logged in. If no, I redirect to a login page. If yes, I want the script to redirect back to foo.zip and this time *not* rewrite it to checkaccess.php.
My original solution was to have the PHP script append something harmless to the end of the URI before redirecting, such as foo.zip?f=12345. I used random values of 'f' to suggest that it was some md5 code, although my rewrite rule did no validity check. :-} This is not optimal, for 2 reasons:
I've experimented with the %{HTTP} and %{ENV} variables, i.e. adding something in checkaccess.php that mod_rewrite would catch after the redirect, but the values don't seem to be found.
Does anyone have any suggestions how I might solve this problem elegantly? I'm convinced that it's possible, but I'm just not enough of a rewrite ace (yet) to figure it out.
Thanks in advance,
Jim
Welcome to WebmasterWorld!
The simplest way might be to rename the zip files (or their directory), or to change the on-page links to the files. The idea being that the visitor requests bar.zip, and checkaccess.php either redirects to the "Please Log in" page or to foo.zip.
The opposite approach being that the visitor requests foo.zip, and checkaccess.php redirects to the "Please Log in" page or to bar.zip where the files are really located... It just depends on whether you want to change the links or the filenames.
These methods are essentially what you're trying to do now, except that the determining factor is the base URL, and not the query string. I didn't mention .htaccess because that part of your existing solution is still needed and unchanged from your current approach -- All of these proposed methods will require a rewrite from the requested zip file to checkaccess.php.
If the zip files are in a subdirectory of their own, then renaming that subdirecty is a painless solution. The visitor requests /check_login/foo.zip, and checkaccess.php redirects to the "Please Log in" page or to /logged_in/foo.zip, where this latter URL is the "real" location of the files. This also has the advantage that you can quickly change the directory name and a single line in .htaccess to 'dodge' direct hotlinking to the zip files.
If you really want to use the querystring method, then you'll need to use mod_rewrite's RewriteCond directive, and check for %{QUERY_STRING}.
As a side-bar issue, you really should not let the script generate an external 301 or 302 redirect, because this exposes the real location of the files to view in the client browser address bar. It would be better to have the script actually read and output the contents of the selected file. If you do that, then this file-reading is done completely internal to the server, and you can place your zip files in a directory path that is completely inaccessible via HTTP -- users then *must* go through the script to GET the files.
Jim
Thanks for your reply.
As a side-bar issue, you really should not let the script generate an external 301 or 302 redirect, because this exposes the real location of the files to view in the client browser address bar. It would be better to have the script actually read and output the contents of the selected file. If you do that, then this file-reading is done completely internal to the server, and you can place your zip files in a directory path that is completely inaccessible via HTTP -- users then *must* go through the script to GET the files.
Yes, that's what I had done at first, and it worked wonderfully on all browsers except -- wait for it -- Windows Explorer. But now I've gone back and studied the problem in more detail and found that sending HTTP headers (like Content-Type) causes problems for Explorer; so I skip the headers in this case, and otherwise it's just the elegant solution I was looking for!
Thanks again,
Jim