Password Protecting Several Directories With One Login
While relaxing mid-day, I wondered what it may be that I take for granted, that I use nearly every day, and yet have never written an article about it. And the answer came to me.
Our site-wide log-in system. A system that lets pretty much any software be password protected. Software that has its own log-in page gets double protection.
This system has one log-in page. Log in there and a cookie is set.
The cookie allows access to any number of password protected directories. The directories are protected with a cookie obtained when logging in through the one log-in page.
Some of the files we have protected in that way are emailing, web content insertion, project time tracking, and server monitoring software.
For better security, either or both the username and the password may contain embedded spaces.
The source code provided in this article has been updated for easier customization. And also to allow more than one username/password set to be specified. (With a separate username for each person allowed access, removing a username later won't affect anybody else's log-in.)
How To Do It
Implementing the system is two steps.
-
The log-in page is uploaded to the server. Put it into a directory that will not be protected with this system; otherwise, the log-in page could not be accessed in order to log in.
-
Put 4 lines of content into the .htaccess file of each directory to be protected.
That's it.
The Log-in Page
Here is the source code for the log-in page. See customization notes below.
<?php # This must be the first line of the file. /* Cookied Directory Password Protection Version 1.0 November 7, 2011 Will Bontrager Software, LLC https://www.willmaster.com/ Copyright 2011 Will Bontrager Software, LLC This software is provided "AS IS," without any warranty of any kind, without even any implied warranty such as merchantability or fitness for a particular purpose. Will Bontrager Software, LLC grants you a royalty free license to use or modify this software provided this notice appears on all copies. */ ////////////////////////////////////////////////////// // // Customizations: // // Specify the cookie name, the cookie value, and how long // the cookie shall last. // The cookie name and the cookie value need to start with // a letter and can be composed of letters, numbers, and // underscore characters. // The cookie lifetime represents the number of days the // cookie shall last. It may be a decimal number. Use // the number 0 to set a volatile cookie, one that will // delete itself when the browser closes. // Change the cookie name and the cookie value to something // different than the representative data this script had // when you received it (security precaution, as others // may be aware of what the script had). $CookieName = "CookieName"; $CookieValue = "CookieValue"; $CookieLifetime = 0.5; // Leave the next line as is: $UNPW = array(); // Below, specify comma-separated usernames and passwords // between quotes, one line for each set, each line // beginning with $UNPW[] = // Usernames may not contain any commas, but passwords may. // Otherwise, both usernames and passwords may contain // any keyboard characters. // Both usernames and passwords may have embedded spaces, // but any spaces at the ends will be ignored. // Usernames are case insensitive. // Passwords are case sensitive. // Remove all representative usernames and passwords this // script had when you received it and specify your own // (security precaution, as others may be aware of what // the script had). $UNPW[] = "username,password"; $UNPW[] = "Will,Bontrager"; $UNPW[] = "fairy tale,oxtail soup"; $UNPW[] = "user4,pass4"; // No further PHP script customizations are necessary. ////////////////////////////////////////////////////// $Message = $UP = array(); if( isset($_POST['un']) and isset($_POST['pw']) ) { foreach( $UNPW as $set) { list($u,$p) = explode(',',$set,2); $UP[trim(strtolower($u))] = trim($p); } $un = trim(strtolower($_POST['un'])); $pw = trim($_POST['pw']); if( empty($un) ) { $Message[] = "Please specify a username."; } elseif( isset($UP[$un]) ) { if( empty($pw) ) { $Message[] = "Please specify a password."; } elseif( $UP[$un] == $pw ) { $domain = preg_replace('/:\d+/','',$_SERVER['HTTP_HOST']); $domain = preg_replace('/^www\./i','',strtolower($domain)); $CookieLifetime = floatval($CookieLifetime); if( preg_match('/[a-z]/',$domain) ) { $domain = ".$domain"; } $life = $CookieLifetime > 0 ? time() + ( floatval($CookieLifetime) * 24 * 60 * 60 ) : 0; setcookie($CookieName,$CookieValue,$life,'/',$domain); } else { $Message[] = "Incorrect password."; } } else { $Message[] = "Incorrect username."; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>Sitewide Log-in</title> </head> <body> <form method="post" action="<?php echo($_SERVER['PHP_SELF']); ?>"> <p> <b> <?php echo(implode('<br><br>',$Message)); ?> </b> </p> <table border="0" cellpadding="5" cellspacing="0"> <tr> <td>Username:</td> <td><input type="text" name="un" style="width:200px;"></td> </tr><tr> <td>Password:</td> <td><input type="password" name="pw" style="width:200px;"></td> </tr><tr> <td> </td> <td><input type="submit" value="Log In" style="width:200px;"></td> </tr> </table> </form> </body> </html>
The above is the source code for an entire PHP web page.
The PHP is to be customized for:
-
The cookie name, the cookie value, and how long the cookie shall last.
-
The usernames and passwords that are allowed to log in.
Comments in the source code in the vicinity of the customizations have instructions.
The visual design of the page may be changed to suit. The form field names need to remain as is.
When customization is complete, upload the page into a directory that will not be password protected with this log-in form. If the log-in form were in the password protected directory, the form could not be accessed to log in.
Make a note of the log-in form's URL. The URL will be needed for the .htaccess file.
The .htaccess File
Here are the four lines to put into the .htaccess file of each directory to be protected. See customization notes below.
RewriteEngine On RewriteBase / RewriteCond %{HTTP_COOKIE} !\bCookieName=CookieValue\b [NC] RewriteRule .* http://www.example.com/members/login.php [L]
The above has two customizations.
-
At line 3: Replace CookieName with the cookie name as specified in the PHP script and replace CookieValue with the cookie value as specified in the PHP script. Leave as is the \b in front of the cookie name and the \b at the end of the cookie value.
-
At line 4: Replace http://www.example.com/members/login.php with the URL to the log-in form.
Each directory to be protected by requiring the use of the log-in form needs those 4 lines in its .htaccess file.
If the directory does not yet have a .htaccess file, create one with those 4 lines. Otherwise, insert the 4 lines into the directory's current .htaccess file.
How To Use It
Now that you have one or more protected directories, put software, web pages, or other files into the directory to keep unauthorized browsers and robots/spiders from accessing them.
Once it's set up, you may end up using it a lot, like I do.
Will Bontrager