[eluser]Tim Skoch[/eluser]
I wanted a simple way to block all public access to a site except for a few whitelisted controllers. This is what I came up with. I'm using a pre_controller hook. I'd like to use a pre_system hook (because I'm irrationally paranoid :-) ), but I cannot think of a good way to get the routed URI's that early.
Anyway - any thoughts from the community? Criticism? Is this secure? Can I make it even simpler? So far it seems to work great! It also maintains user activity timestamps (for logged-in users only) in session variables, and expires logins automatically.
The hook definition:
Code:
$hook['pre_controller'] = array(
'class' => '',
'function' => 'startSession',
'filename' => 'login.php',
'filepath' => 'hooks',
'params' => array()
);
The hook script:
Code:
<?
function startSession() {
session_start();
$site_url = 'http://example.com/';
$loginLength = 60 * 60; // In seconds
$controllerWhitelist = array('view'); // An array of safe controllers which anyone can access
$URI =& load_class('URI'); // Allows us to call the URI class early (since it hasn't been defined yet)
if (!in_array($URI->rsegment(1), $controllerWhitelist)) {
if (isset($_SESSION['name'])) {
// The user is already logged in
if ( isset( $_SESSION['lastactivity'])
&& is_numeric( $_SESSION['lastactivity'])
&& ((time()- $_SESSION['lastactivity'])>$loginLength)
) {
dieFcn('Login expired<br /><a href="'.$site_url.'">home</a>');
}
$_SESSION['lastactivity'] = time();
} else {
$usernameField = 'username';
$passwordField = 'password';
if ( isset( $_POST[$usernameField])
&& isset( $_POST[$passwordField])) {
// Credentials were sent, now check them
mysql_connect('db_host', 'db_userName', 'db_pw') or die('login error');
mysql_select_db('db_dbName') or die('login error');
$result = mysql_query("SELECT * FROM users WHERE name='".mysql_real_escape_string($_POST[$usernameField])."' AND pw='".mysql_real_escape_string(md5($_POST[$passwordField]))."'");
if (mysql_num_rows($result)==1) {
$user=mysql_fetch_assoc($result);
$_SESSION['name'] = $user['name'];;
$_SESSION['logintime'] = time();
$_SESSION['lastactivity'] = time();
} else {
dieFcn('invalid login<br /><a href="'.$site_url.'">home</a>');
}
} else {
$dieString = <<<HEREDOC
Hey! Here is some message explaining that users need to
log in to view this portion of the site.
<br />
<form method="post" action="">
<br /><input type="text" name="$usernameField"/>
<br /><input type="password" name="$passwordField"/>
<br /><input type="submit" value="Login"/>
</form>
HEREDOC;
dieFcn($dieString);
}
}
}
}
function dieFcn($message='') {
session_destroy();
die($message);
}
?>