I’m going to describe the class I created to handle signup/login/authentication at happypolack.com.
If you’d like a demo, create an account at Happy Polack
.
The Database Structure
First, what is it going to look like in the database? Well, here’s what I used:

Generated using MySQL Workbench
Take note of the indexes used. I have a foreign key relating the users and the groups table (1-1 for now). I also have a unique index on the username to prevent the same username. Lastly, I have a regular index on the email address to make searching that field faster (useful if they forgot their password).
The other thing to note is that both password and cookie have a datatype of CHAR(64). This is because I encrypted the password using a SHA256 algorithm, which is WAY stronger than md5, before placing it in the database (this is PHPs hash(“sha256″,$unenc_password) function). For the cookie field, I use that algorithm on the uniq_id() function built into PHP. I’ll get to that in a minute.
The Class Structure
class AccountController {
// Initialize variables to something arbitrary
private $group_id = -1;
private $user_id = -1;
private $username = '';
public function signup($username, $password, $email){...}
public function login($username, $password){...}
public function logout(){...}
public function authenticate($group_id = 0){...}
public function is_logged_in(){...}
public function is_admin(){...}
}
Excellent! We got the basic functionality out of the way. We are able to signup/login/logout/authenticate. We can even pass a group_id to authenticate to make sure they are part of a specific group.
Signup
public function signup($username, $password, $email) {
$dbconn = @Database::grab(); // This WILL be different for you. I use a simple MySQLi wrapper.
$origpassword = $password; // store original password to send to them
$password = hash('sha256', $password);
if(!$dbconn->query($query))
return false;
else
{
// Send a nice email
$message = '<b>Account Information:</b>';
$message .= '<p>Username: '.$username;
$message .= '</p><p>Password: '.$origpassword;
$message .= '</p><p>Your profile: http://happypolack.com/user/'.$username.'</p>;
send_mail( $email, "Welcome to Happy Polack!", "Hello and Welcome to Happy Polack!", $message );
}
return true;
}
There you have it! Now we can signup, well… except for the send_mail piece, let me give you the code for that:
function send_mail($to, $subject, $title, $msg)
{
$headers = 'From: Happy Polack <you@example.com>'. "\r\n".
'Reply-To: you@example.com' . "\r\n" .
'X-Mailer: PHP/' .phpversion(). "\r\n";
$headers .= 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$message = '<h1>'. $title.'</h1>';
$message .= $msg;
mail( $to, $subject, $message, $headers);
}
Basically, this nifty function automatically sets up the headers so we can use HTML in our e-mails and it automatically formats various features (this implementation could be spruced up with some neat css too).
Login
public function login($username, $password) {
$dbconn = @Database::grab();
$epassword = hash("sha256",$password); // Encrypt using SHA256. We could also "salt" the password before hashing for added security.
$query = "SELECT id, group_id FROM users WHERE username = '$username' AND password = '$epassword' LIMIT 1";
$qData = $dbconn->query($query) ;
if( $qData->num_rows > 0 )
{
$userData = $qData->fetch_array();
$cookie = generate_token();
$userID = $userData['id'];
$query = "UPDATE users SET cookie = '$cookie' WHERE username = '$username' AND password = '$epassword'";
if($dbconn->query($Query))
{
$this->user_id = $userID;
$this->group_id = $userData['group_id'];
$expire_time = 60*60*24*7+time(); // About one week
// When we create the cookies, we pass the cookie's name, the value, the expire time and what piece of the site the cookie is valid on. I specify "/" to allow it to be usable throughout the whole website.
setcookie("id", $userID, $expire_time, "/");
setcookie("cookie", $cookie, $expire_time, "/");
setcookie("username", $username, $expire_time, "/");
// This piece is so that the COOKIE values are set immediately. When I left this piece out, I noticed it would take an extra page load for the cookies to register. This is because the cookies are generally sent with everyday headers and *it seems* that they are not processed right away.
$_COOKIE['id'] = $userID;
$_COOKIE['cookie'] = $cookie;
$_COOKIE['username'] = $username;
return true; // SUCCESS, now logged in!
}
}
return false; // Bummer!
}
What’s happening here? Well, let’s get a pretty picture to clarify the order a little bit:

Generated with yUML - Does this help?
In easier terms: Check if the user is in the database -> if he is, put a random value into his cookie field for later authentication and set his cookies.
That reminds me, here is one last function, generate_token(), that is pretty essential, and simple, to get a random string of length 64.
// Return a random string of length 64
function generate_token() {
return hash('sha256', uniqid(mt_rand(), true));
}
Next Time
Wow! Progress has been made. But there’s more to be had. We still need an authenticate function as well as a way to logout!
Phew.