views:

409

answers:

2

We have a protected directory on our site, where users are required to login using the .htacces system.

I know we can get the username of the person thats logged in through a PHP variable

$username = $_SERVER['REMOTE_USER'];

I'm wondering if it's possible to show ALL users logged in?

This way we could show something at the top like "The following users are logged in: "

Also, could someone clarify how the sessions work with htaccess, does a person only have to re-login if they close the browser, or does it time out? Thanks

+1  A: 

.htaccess Basic Authentication is just that - only authentication. There is no concept of a session associated with it, and thus at any one point in time the server has no idea how many clients have current authentication credentials.

As long as a browser has authentication details, the session won't time out. Typically, only restarting the browser will result in a browser 'forgetting' it's authentication details.

Ian Gregory
+1  A: 

It is true that BASIC Auth has no concept of sessions. However, sessions is not the only way to authenticate users, or to keep track of how many users are logged in. In fact, HTTP is stateless, and so is HTTP Sessions. You can only guess how many are logged in via the number of recent active (modified recently) sessions.

You can implement BASIC Auth with PHP. http://php.net/manual/en/features.http-auth.php

You can guess how many are logged in just by counting the number of authentications made in the last 5 minutes, or 10 minutes etc. This would be just as accurate as HTTP sessions.

Eg:

Create a file called basic-auth.php or similar. This is the basic example from PHP.net

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>

You can then require() this file from every file/directory you want to protect. However, all downloads will have to be validated by PHP now. Remove your .htaccess basic authentication. Since you'll have PHP do it.

Now you modify it to autheticate users.

One thing to note is that BASIC Auth is only a specification for HTTP authentication. It does not specify how to authenticate. Since you're using Apache, how you authenticate is specific to Apache. You should have created a password file for Apache, similar to mentioned here: http://httpd.apache.org/docs/1.3/howto/auth.html#basicconfig

Apache uses three hashing functions. Either crypt, md5 or sha1. So if you want to use the same password file, then you need to know which hash you're using.

Here is an example for SHA1:

Basically you'll just go through each line of the password file, and if it has the user, check if the supplied password matches. The file looks something like:

user1:passwordhash1 user2:passwordhash2

Which is just one user and their password hash per line, separated with ":".

See here for how the hash is generated: http://httpd.apache.org/docs/trunk/misc/password%5Fencryptions.html

Your code would be something like this (untested) :

<?php

$authenticated = false;

// a user and password was supplied
if (isset($_SERVER['PHP_AUTH_USER'])) {
    $user = $_SERVER['PHP_AUTH_USER'];
    $pass = $_SERVER['PHP_AUTH_PW'];
    $hash = '{SHA}' . base64_encode(sha1($password, TRUE));

    $password_file = '/path/to/your/passwords/file';
    $lines = file($password_file);

    // find the user in the password file
    foreach($lines as $line) {
       list($_user, $_hash) = explode(":", $line);
       if ($_user == $user) {
          // if the hash matches, then their password was correct
          if ($hash == $_hash) {
             $authenticated = true;
          }
          break;
       }
    }
}

if (!$authenticated) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'You need to log in to access the downloads';
    exit;
}

// log file
$log_file = '/path/to/authentication/logs.log';

$lines = file($log_file);
$time = time();
$mins = 5; // last 5 mins

// write this user to log
$lines[] = $user.":".time();

// remove log entries older then $mins
// also count unique user entries
$unique_users = array();
foreach($lines as $i=>$line) {
   list($_user, $_time) = explode(":", $line);
   if ($time > $_time + 60*$mins) unset($lines[$i]);
   else $unique_users[$user] =  isset($unique_users[$user]) ? $unique_users[$user]+1 : 0;
}

// write log file to disk
file_put_contents($log_file, implode("\n", $lines));

// users online 
$users_online_count = count($unique_users);


?>

Of course, you can implement any authentication method. You could use a database, or write your own file formats, etc.

bucabay