After reading a question on StackOverflow I’ve been inspired to help him out by writing a PHP/MySQL implementation of Charles Miller’s “Persistent Login Cookie Best Practice” For this tutorial I’m going to assume you already have a PHP system with user login.
CREATE TABLE user_sessions (
user_id INT(11) UNSIGNED NOT NULL,
session VARCHAR(39) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
PRIMARY KEY (user_id, session)
);
First, we need to update the site when you login to store the session into the cookie. This code will go with your current login system.
if (/* Code that verifies credentials */) {
// ... code to log user into session
PersistentAuth::login($userId);
}
Second, we want to check if a new user to the site has cookie credentials. This code will go at the beginning of your code. It checks, first, are we already logged in in our $_SESSION? if not, try the cookie-based login.
if (/* !loggedIn() */ && ($userId = PersistentAuth::cookieLogin())) {
// ... use $userId to log user into session
}
Third, in accordance with Charles Miller’s article we cannot allow a user to the following sections if they are logged in via cookie:
- Changing the user’s password
- Changing the user’s email address (especially if email-based password recovery is used)
- Any access to the user’s address, payment details or financial information
- Any ability to make a purchase
Code:
if (PersistentAuth::isCookieLogin()) {
// User is logged in via cookie and don't have access to this
// section. We need to ask them for the password. Maybe send
// them to some login page?
// TODO ask for password or send to a password page
}
To get all the code for the PersistentAuth class checkout my site here: http://www.chrislondon.co/php-persistent-login/
With this PersistentAuth class there are a few changes you will have to make. One you’ll have to change the getDb() function to return an instance of your database. I’m using PDO in this example. I have it set up for every page refresh clear the database of old sessions. The best way to handle this is to use a cron. If you do set up a cron then change the USE_CRON flag to true in the class settings