Drupal 6

Need help with (final?) release of Panels for Drupal 6

Tags: 

After more than two and a half years since the last release, we need some help putting together what might be the final release of Panels for Drupal 6:

There are several patches that are probably a-ok but they just need a final review before being committed, and your help with this would be very much appreciated. If we can get some help getting the existing patches to RTBC status, I've volunteered to join as a co-maintainer to do this release, just so the module can have a grand final exist.

Simple HTTP authentication for Drupal sites [updated]

Tags: 

There are lots of times when you need some simple password protection, typically via HTTP Authentication, on your Drupal site; my most common use being for publicly accessible development sites that I don't want accidentally indexed by search engines. Thanks to some simple code, based on something originally written by someone at Acquia (thank you, phantom coder!), it's pretty easy to add HTTP authentication to your site and then enable it per site instance; this will keep your codebase and your modules list pretty clean. FYI this works equally well on both Drupal 6 and 7.

There are three parts to this solution:

  1. Modifying the .htaccess file to allow the authentication.
  2. A function that can be added to settings.php or elsewhere in the execution process.
  3. A function call that is used as the on/off switch.

Step 1: Customize the .htaccess file

The first piece is a new line that needs to be added to the .htaccess file:

  # Password protection.
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

This should be added at the end of the file, just before the final , so that it looks like so:

  # Password protection.
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>

Step 2: Add the Special Function

All of the logic is housed in a PHP function that needs to be added to your site, probably the best location being your settings.php file.

/**
 * Password protect the site with a single function.
 */
function secure_the_site_please($username = 'monkey', $password = 'monkey', $message = 'This site is protected') {
  // Password protect this site but ignore drush and other command-line
  // environments.
  if (php_sapi_name() != 'cli') {
    // PHP-cgi fix.
    $a = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6));
    if ((strlen($a) == 0) || (strcasecmp($a, ":") == 0)) {
      header('WWW-Authenticate: Basic realm="Private"');
      header('HTTP/1.0 401 Unauthorized');
    }
    else {
      list($entered_username, $entered_password) = explode(':', $a);
      $_SERVER['PHP_AUTH_USER'] = $entered_username;
      $_SERVER['PHP_AUTH_PW'] = $entered_password;
    }
    if (!(isset($_SERVER['PHP_AUTH_USER']) && ($_SERVER['PHP_AUTH_USER'] == $username && $_SERVER['PHP_AUTH_PW'] == $password))) {
      header('WWW-Authenticate: Basic realm="' . $message . '"');
      header('HTTP/1.0 401 Unauthorized');
      // Fallback message when the user presses cancel / escape.
      echo 'Access denied';
      exit;
    }
  }
}

Step 3: The on/off switch

The final step is to add the following line to the end of the settings.php file somewhere after the function above:

// Password protect the site.
secure_the_site_please();

This is the master on/off switch that lets you control the authentication functionality. You can easily disable it as needed just by commenting out the line, then the site will continue to work as-is without any problems.

You may have noticed that the function had some arguments? You can use these arguments to change the default username & password from "monkey" to something more relevant, or easily remembered, e.g.:

// Use a custom username & password.
secure_the_site_please('albatross', 'mint');

The function accepts a third argument which controls the message displayed so it can be changed from the default "This site is protected" to something more suitable, e.g.:

// Use a custom username & password.
secure_the_site_please('albatross', 'mint', 'What flavor is it?');

Or even:

// Use a custom username, password & message.
secure_the_site_please('albatross', 'mint', 'The username is "albatross" and the password is "mint"');

Final notes & thoughts

The main reason I like this solution vs e.g. SecureSite is that it doesn't require a different set of modules for one site vs another, all that's needed is one change to the settings.php file and it's easily turned on or off.

I include a settings_shared.php at the top of each settings.php file to store shared settings between all of the per-hostname site instances, and this is where I added the function. On one site I had 44 different per-hostname settings files for four different instances of eleven sites, half of which needed to be protected, so it was very easy to have the function in the settings_shared.php file and then just add the function call to the individual settings.php files.

The HTTP authentication variable, "HTTP_AUTHORIZATION", was so-named so it could be compatible with Drupad, which also uses HTTP authentication; please note that you currently must have this authentication disabled in order for Drupad to work.

So, what do you use to product your in-development sites from prying eyes or being accidentally scraped by search engines?

Updated April 9th:
Thanks for all the feedback. It turns out that the Shield module can basically do this too, using variables (that can be added to settings.php) to control everything; also the SecureSite module has an on/off switch variable so in effect it could be used too. FYI the reason I didn't use any Drupal 7 functions was so that the same code snippet would work with D6 too.

Updated April 12th:
Fixed a small =) bug that inadvertently allowed any password to be passed through, once the username matched.

Subscribe to Drupal 6