PHP login handling tutorial – sessions & cookies included
I see a lot of people trying to write code to authenticate users logging into a PHP website. This is some code I cobbled together in december of 2008 and it has worked problem free since then.
// I've already sanitized all GET, POST, and COOKIE data at this point.
function check_login() {
global $DB;
$login_justnow=false;
// if the user isn't logged in and they're POSTing a login request, process it
if(!get_session('user/id') && isset($_POST['login']) {
$name=$_POST['login_name']; $remember_me=isset($_POST['remember_me'])?1:0;
$pass=md5($_POST['login_pass']);
$user_id=$DB->QueryXY("SELECT id FROM `users` WHERE name='$name' AND pass='$pass' AND confirmed='1' LIMIT 1");
if(isset($user_id)) {
account_login($user_id,$remember_me);
$login_justnow=true;
$name=get_session("user/given_name")?', '.get_session("user/given_name"):'';
add_notice("Welcome$name!");
} else {
add_error("Login failed.");
account_logout();
}
}
// if the user isn't logged in but has a COOKIE, process it
if(!get_session("user/id") && isset($_COOKIE["remember_me"]) ) {
list($user_id,$cookie_code)=@unserialize(stripslashes($_COOKIE["remember_me"]));
if(isset($user_id) && isset($cookie_code)) {
$cookie=md5($cookie_code);
$result=$DB->QueryArray("SELECT * FROM `users` WHERE id='$user_id' AND cookie='$cookie' AND confirmed='1' LIMIT 1");
if(count($result)) {
account_login($user_id,true);
$login_justnow=true;
$name=get_session("user/given_name")?', '.get_session("user/given_name"):'';
add_notice("Welcome$name!");
}
}
}
// if the user's session says they're logged in, process it
if(get_session("user/id") && $login_justnow===false) {
$user_id=get_session("user/id");
$cookie=get_session("user/cookie");
$ip=get_session("user/ip");
$session=session_id();
$query="SELECT * FROM `users` WHERE id='$user_id' AND ip='$ip' AND session='$session' AND cookie='$cookie' AND confirmed='1' LIMIT 1";
$result=$DB->DoQuery($query);
if($DB->NumRows($result)) {
account_login($user_id,false);
} else {
add_error("Session security failed.");
account_logout();
}
$DB->EndQuery($result);
}
// check if the user actually has rights to this part of the site - your implementation may vary
}
function account_login($user_id,$remember_me) {
global $DB;
if(user_is_logged_in())
return;
// update cookie
if($remember_me==true) {
$cookie_code=generate_random_string();
$cookie_str=serialize(array($user_id, $cookie_code));
setcookie('remember_me', $cookie_str, time() + 60*60*24*30, '/');
add_session("user/cookie",$cookie_code);
} else {
remove_session("user/cookie");
}
// update session security
$ip=$_SERVER['REMOTE_ADDR'];
$session=session_id();
$cookie_code=get_session("user/cookie");
$cookie=md5($cookie_code);
$DB->DoQuery("UPDATE `users` SET last_on=NOW(), session='$session'"
.(($cookie_code!='')?", cookie='".$cookie."'":"")
.", ip='$ip' WHERE id='$user_id' LIMIT 1");
// update session info
$result=$DB->DoQuery("SELECT * FROM `users` WHERE id='$user_id' LIMIT 1");
$row=$DB->FetchAssoc($result);
foreach($row as $k=>$v) {
add_session("user/".$k,$v);
}
$DB->EndQuery($result);
// check if any other part of your system needs to know about a user logging in.
}
function user_is_logged_in() {
return get_session("user/id")!=0;
}
function generate_random_string($length=32) {
$random="";
srand((double)microtime()*1000000);
$char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$char_list.= "abcdefghijklmnopqrstuvwxyz";
$char_list.= "1234567890";
for($i=0;$i<$length;++$i) {
$random.=substr($char_list,(rand()%(strlen($char_list))), 1);
}
return $random;
}