Keeping in mind that we’re passing the session identifier in a cookie, and this already requires that an attack be used to compromise this cookie (and likely all HTTP headers as well), we should pass this fingerprint as a URL variable. This must be in all URLs as if it were the session identifier, because both should be required in order for a session to be automatically continued (in addition to all checks passing).
In order to make sure that our real users aren’t treated like criminals, simply prompt for a password if a check fails. If there is an error that incorrectly suspects a user of an impersonation attack, prompting for a password before continuing is the least offensive way to handle the situation.
There are many different ways of complicating impersonation and protecting your applications from session hijacking. Doing more than just session_start() is a good step in the right direction! Always remember that making things difficult for criminals or vandals is always the aim of security.
Until Next Time–Happy Sessions!