Simple PHP .htpasswd 🔑 Manager

Simple PHP .htpasswd 🔑 Manager

Sometimes simplicity is also convenient, and in the case of authentication on the most popular web server, Apache, .htpasswd fits the bill

You may opt for a PHP/MySQL login which in itself is simple enough, but requires the availability of MySQL. If you are on a cheap shared host, MySQL may not be available or is available for a fee.

About .htpasswd

.htpasswd can allow you to authenticate users and restrict access to particular areas of your site. Usernames and passwords are stored in a plain text file with passwords encrypted, while the default setup for Apache ‘hides’ .htpasswd from direct viewing because the filename begins with a period. To enable .htpasswd, you must declare in .htaccess (or apache2.conf) that a particular directory requires authentication, and indicate what file contains your username and password combinations.

An example .htaccess file indicating that /adminarea/ requires authentication, that should reside in the same folder you require authentication for. Note that the path you reference to the .htpasswd file must be an absolute path:

AuthUserFile /var/www/adminarea/.htpasswd
AuthType Basic
AuthName "Admin"
Require valid-user

And an example .htpasswd file that will reside at /var/www/adminarea/.htpasswd for the purposes of this example

admin:SKuDMdWca/4yk
stefan:CVWMU2otVImPk
michael:JZIuI2F0.uxC.
james:PiECF6UFNQe7s
billg:Zs/QmY/rQHTtI

Managing .htpasswd

Because some shared hosts restrict your available tools and access, it is sometimes helpful to have a PHP script that can manage your .htpasswd file when you are unable to use the command line. If SSH is disabled or command line execution is forbidden, as is often the case on shared hosts, your only other current option is to manage htpasswd via an admin area such as CPanel, which can be slow and inefficient. With this in hand, you may find the following script of interest.

This class will add users, delete users, check if users exists and update existing user’s passwords…

// Save as .htpasswd.php
class htpasswd {
    var $fp;
    var $filename;
 
    function htpasswd($filename) {
        @$this->fp = fopen($filename,'r+') or die('Invalid file name');
        $this->filename = $filename;
    }
 
    function user_exists($username) {
        rewind($this->fp);
            while(!feof($this->fp)) {
                $line = rtrim(fgets($this->fp));
                if(!$line)
                    continue;
                $lusername = explode(":",$line)[0];
                if($lusername == $username)
                    return 1;
            }
        return 0;
    }
 
    function user_add($username,$password) {
        if($this->user_exists($username))
            return false;
        fseek($this->fp,0,SEEK_END);
        fwrite($this->fp,$username.':'.crypt($password,substr(str_replace('+','.',base64_encode(pack('N4', mt_rand(),mt_rand(),mt_rand(),mt_rand()))),0,22))."\n");
        return true;
    }
 
    function user_delete($username) {
        $data = '';
        rewind($this->fp);
        while(!feof($this->fp)) {
            $line = rtrim(fgets($this->fp));
            if(!$line)
                continue;
            $lusername = explode(":",$line)[0];
            if($lusername != $username)
                $data .= $line."\n";
        }
        $this->fp = fopen($this->filename,'w');
        fwrite($this->fp,rtrim($data).(trim($data) ? "\n" : ''));
        fclose($this->fp);
        $this->fp = fopen($this->filename,'r+');
        return true;
    }
 
    function user_update($username,$password) {
        rewind($this->fp);
            while(!feof($this->fp)) {
                $line = rtrim(fgets($this->fp));
                if(!$line)
                    continue;
                $lusername = explode(":",$line)[0];
                if($lusername == $username) {
                    fseek($this->fp,(-15 - strlen($username)),SEEK_CUR);
                    fwrite($this->fp,$username.':'.crypt($password,substr(str_replace('+','.',base64_encode(pack('N4', mt_rand(),mt_rand(),mt_rand(),mt_rand()))),0,22))."\n");
                    return true;
                }
            }
        return false;
    }
}

This gives you some basic examples to work with:

include_once('htpasswd.php');
$htpasswd = new htpasswd('/var/www/adminarea/.htpasswd'); // path to your .htpasswd file
 
// A list of random user names
$users = array('admin','stefan','santa');
// Checking to see which users exist
foreach($users as $user)
	echo "The username $user does ".($htpasswd->user_exists($user) ? 'exist' : 'not exist')."\n";
 
// Trying to add all usernames with password 'apples'
	foreach($users as $user)
echo "The username $user ".($htpasswd->user_add($user,'apples') ? 'has been added' : 'already exists')."\n";
 
// Trying to remove user 'santa'
echo "Removing user 'santa' if present\n";
$htpasswd->user_delete('santa');
// Trying to update user stefan with new password 'oranges', will add user if they do not exist
if($htpasswd->user_update('stefan','oranges'))
echo "Updated password for 'stefan'\n";

Summary of .htpasswd Class

Before running, ensure you have your .htaccess and .htpasswd files created already, .htpasswd can be left blank.

See also  What's new in PHP 8.1

$htpasswd->htpasswd(‘/var/www/adminarea/.htpasswd’); – Upon initiating the class, A file pointer is created, as all the functions require reading and writing to the file

$htpasswd->user_exists($username) – Accepts the $username variable and reads .htpasswd line by line until a username within it matches $username. Returns false if $username is not matched.

$htpasswd->user_add($username,$password) – Accepts $username and $password and checks whether the user already exists. If not, $username nad $password is written to a newline at the end of the .htpasswd file.

$htpasswd->user_delete($username) – Deletes $username from the .htpasswd file. The file is iterated through line by line and a string is built containing all the details minus $username’s credentials. The resulting string is then written to .htpasswd, effectively deleting $username’s account.

$htpasswd->user_update($username,$password) – Updates $password for $username. The file is read line by line until $username is matched, after which the password is then updated. The function will return false is the username is not found.

whoami
Stefan Pejcic
Join the discussion

I enjoy constructive responses and professional comments to my posts, and invite anyone to comment or link to my site.