• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Uber-simple login script...

#1
[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 />
                    &lt;form method="post" action=""&gt;
                        <br />&lt;input type="text"        name="$usernameField"/&gt;
                        <br />&lt;input type="password"    name="$passwordField"/&gt;
                        <br />&lt;input type="submit"      value="Login"/&gt;
                    &lt;/form&gt;
HEREDOC;
                dieFcn($dieString);
            }
        }
    }
}

function dieFcn($message='') {
    session_destroy();
    die($message);
}
?&gt;

#2
[eluser]crumpet[/eluser]
if you really want to be secure you can use javascript to md5 the password before sending it encase someone is listening - or ssh i guess.

Also this statement : isset( $_SESSION['lastactivity'])
&& is_numeric( $_SESSION['lastactivity'])
&& ((time()- $_SESSION['lastactivity'])>$loginLength)
will fail if last activity is not a number.. so a user could steal a cookie and tamper it to have lastactivity = 'a' or something and it would last forever...

#3
[eluser]Tim Skoch[/eluser]
Thanks!

The JavaScript idea sounds fun.

I don't understand how someone could tamper with a $_SESSION[] variable, though. When PHP uses sessions, the only thing it sends to the user is their session ID - it stores all of the data on the server (at least that's what I understood - but I've been wrong before!). Hence, all they could POTENTIALLY do is spoof a session which wasn't theirs. But I don't think they can inject arbitrary data into the $_SERVER variables.

Anyway, thanks for the input! :-)

#4
[eluser]crumpet[/eluser]
i don't think that php does that natively. you need ot write a session library specifically to have it store the data on the server. You can enable it in the codeigniter configuration files.. but you have to create a special table in your database for the session to be stored in.

#5
[eluser]Tim Skoch[/eluser]
Hrmmm, looking into it further I really think PHP sessions only store the session ID on the client - all of the other data looks like it's stored on the server, isolated from the user. :-S Anyone else care to chime in?

#6
[eluser]crumpet[/eluser]
sorry, you are right on this one. I wonder why people in the community seem to value sessions storing in mysql database...
anyone?

#7
[eluser]Tim Skoch[/eluser]
Maybe just the ease with which doing so allows you to save historical session info? User tracking? Unless you plan to save the info, I don't see any advantage to putting it into a database. Hmmm...


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.