In the first part of this series we went over how a cookie works and what can be done to secure them. In this section we’re going to go over ways to add additional security to the session beyond the cookie itself.
By the end of this article we will written our own wrapper class for “session_start” that protects our session from a number of attacks while taking into account some of the unique challenges presented by modern ajax-heavy websites.
Contents
Session Specific Attacks
Through the use of sessions your identity is maintained as you use a website, and just as in real life identity theft is a concern. By taking over your session an attacker would essentially become you on a website, with access to all of the actions, information and privileges that entails.
The main thing that an attacker needs to steal a session is the session ID. There are three ways an attacker normally goings about doing this, all of which can be protected against but are, by default, completely open.
- Guess the ID: most session handlers generate ids that make this impractical.
- Steal the ID: by using malware, sniffing the network, or exploiting javascript exploits attackers can get the value from the cookie itself.
- Set the ID: rather than steal or guess the ID an attacker may try and set it to a value they choose.
Starting the Session
The default session setup is not at all secure by itself, so we’re going to create a wrapper to add the security we need. To make this code more portable we’re going to build it as a static function of a php class called SessionManager.
To begin our sessionStart function is going to set the name cookie options for the session. Like all cookies we’re going to need to make some decisions about what is going to need access to the session ID. Since these options depend on the application itself lets add arguments we can change based on our specific needs.
For security we can hardcode the “HttpOnly” argument, as session ids are often the juiciest target for cross site scripting attacks.
class SessionManager
{
static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
// Set the cookie name before we start.
session_name($name . '_Session');
// Set the domain to default to the current domain.
$domain = isset($domain) ? $domain : isset($_SERVER['SERVER_NAME']);
// Set the default secure value to whether the site is being accessed with SSL
$https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);
// Set the cookie settings and start the session
session_set_cookie_params($limit, $path, $domain, $secure, true);
session_start();
}
}
Using the new class is as easy as including it and running one line but additional options can make it more restrictive.
SessionManage::sessionStart('InstallationName');
SessionManage::sessionStart('Blog_myBlog', 0, '/myBlog/', 'www.site.com');
SessionManage::sessionStart('Accounts_Bank', 0, '/', 'accounts.bank.com', true);
Lock the Session to a Host
Now that our wrapper class is in place and functional we can start building in additional security by restricting the session to the same IP address and User Agent (or browser) as when the session was first opened. This way if the session ID is stolen or guessed the attacker still has to get ahold of the user agent (admittedly not too difficult if they got the session ID) and somehow find a way to get the same IP address.
These attacks only help if the user is not on the same network. The user agent check only adds minor security, since many attacks that compromise the cookie are going to do the same to the user agent. If an attacker is on the same network as the target there is a good chance they already have the same external IP address, as it is pretty common for a network to use private internal addresses while presenting only a single IP address to the internet. This is why it is important to evaluate the need for SSL.
We’re going to add these new checks to our class in the function preventHijacking. This function will return false on new sessions or when a session is loaded by a host with a different IP address or browser. preventHijacking will true if the session is valid and false otherwise. This means it will return false not just on malicious attempts but completely new sessions as well.
static protected function preventHijacking()
{
if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent']))
return false;
if ($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR'])
return false;
if( $_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT'])
return false;
return true;
}
Now that we have a way to identify hijacking attempts we need to set up a way to respond to them. For us this means two things- clearing out the old session data and inserting the IP address and user agent into the new session.
static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
...
session_start();
if(!self::preventHijacking())
{
$_SESSION = array();
$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
}
}
Session Fixation
So far we have effectively eliminated the possibility of brute force guessing. We’ve also made it so any attempts at capturing the session ID would require the attacker to be on the same network as the user in order to take advantage of that ID, while also discussing enforcing SSL to make capturing the session more difficult through traditional means. However, what if the attacker could set the session ID themselves?
By getting the user to follow a link with a session ID in it the attacker can trick the user into starting a session with the ID of the attacker’s choosing. Rather than guess or steal an ID the attacker will have it right from the start. Many web environments, including PHP, allow session ids to be set through the URL, primarily to get around systems which do not support cookies. Just like with regular cookies the value sent by the client is the value used for the ID, so in this case the value in the URL becomes the session ID.
The solution to this is to change the session ID. How often you do this is tends to be a matter of great debate, but at the bare minimum the ID should be changed when new sessions are created and when the user changes privileges (logs in or out).
A First Attempt At Regenerating the ID
Regenerating the ID is fairly simply in php. Deceptively simple one might say. The function “session_regenerate_id” lets us tell the system to use a new ID. It can also optionally delete the old session.
// Leaves old session intact
session_regenerate_id();
// Deletes old session
session_regenerate_id(true);
If you don’t delete the old session then it is still vulnerable to hijacking and whatever access it had can be granted to an attacker. If you’re changing the session ID often without deleting the old ones you could be creating more holes by leaving a trail of old, but valid, sessions.
Regenerating the ID in the World of Ajax
If an application creates a lot of quick connections to the server some interesting things can happen. PHP, and many other languages, restricts access to the session data to one running script at a time, so if multiple requests come in that try to access the session data the second request (and any other) gets queued up. When the first request changes the ID and deletes the old session the second request still has the old session ID which no longer exists. This results in a third, new session being opened and generally means your user gets logged out.
This bug is ridiculously hard to diagnose as the timing of not just the requests but the ID regeneration has to be just right. In sites that don’t make requests to the server using javascript this type of bug may never be encountered at all, as the time between page loads is more than long enough for the browser to have updated its session info. For sites that make use of ajax techniques, however, this issue will have a chance of occurring whenever the session ID is changed.
In our final update to the SessionManager class we’re going to write a fix for this problem. Rather than delete the session immediately when we change the ID, we’re going to mark the old session as obsolete and mark it to expire in ten seconds. This way any queued up requests will still have access to the expired session but we don’t have to leave it open forever.
To accomplish this we’re going to add the regenerateSession function. This function adds the obsolete flag and expiration to the session, regenerates the ID to create the new session and saves them both. It then reopens the new session and removes the obsolete flag. Unlike our other internal functions we are leaving this one open for use outside the class so that it can be tied into login scripts.
static function regenerateSession()
{
// If this session is obsolete it means there already is a new id
if(isset($_SESSION['OBSOLETE']) || $_SESSION['OBSOLETE'] == true)
return;
// Set current session to expire in 10 seconds
$_SESSION['OBSOLETE'] = true;
$_SESSION['EXPIRES'] = time() + 10;
// Create new session without destroying the old one
session_regenerate_id(false);
// Grab current session ID and close both sessions to allow other scripts to use them
$newSession = session_id();
session_write_close();
// Set session ID to the new one, and start it back up again
session_id($newSession);
session_start();
// Now we unset the obsolete and expiration values for the session we want to keep
unset($_SESSION['OBSOLETE']);
unset($_SESSION['EXPIRES']);
}
We need to add another function to check for the obsolete flag and to see if the session has expired.
static protected function validateSession()
{
if( isset($_SESSION['OBSOLETE']) && !isset($_SESSION['EXPIRES']) )
return false;
if(isset($_SESSION['EXPIRES']) && $_SESSION['EXPIRES'] < time())
return false;
return true;
}
Finally, in the last change to our SessionManager, we need to update our SessionStart function. It needs to call the regenerateSession function on new requests and periodically after that, as well as destroy the session if it is invalid. Here is the complete SessionStart function.
static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
// Set the cookie name
session_name($name . '_Session');
// Set SSL level
$https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);
// Set session cookie options
session_set_cookie_params($limit, $path, $domain, $https, true);
session_start();
// Make sure the session hasn't expired, and destroy it if it has
if(self::validateSession())
{
// Check to see if the session is new or a hijacking attempt
if(!self::preventHijacking())
{
// Reset session data and regenerate id
$_SESSION = array();
$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
self::regenerateSession();
// Give a 5% chance of the session id changing on any request
}elseif(rand(1, 100) <= 5){
self::regenerateSession();
}
}else{
$_SESSION = array();
session_destroy();
session_start();
}
}
Summary
At times it amazes me how complex something as simple as an ID- what is essentially just a string of random characters- can turn out to be. While you can certainly use this class for all of your own projects here is what you need to remember when building your own session manager.
Session IDs are attacked by guessing, capturing or setting the id. You can protect against this in your own applications by …
- Securing the cookie to make stealing the ID harder
- Limiting the session to a specific host to make attacks more difficult
- Changing the ID when escalating privileges and throughout the session life.
Here is the complete Session.class.php file for your reference.
Apprediate this post. Let me try it out.
I’m having trouble understanding one line in function validateSession(). Why do we need this:
if( isset($_SESSION[‘OBSOLETE’]) && !isset($_SESSION[‘EXPIRES’]) )
It seems to me that any time ‘OBSOLETE’ is set, ‘EXPIRES’ will also be set. In other words, isn’t it sufficient to check:
if(isset($_SESSION[‘EXPIRES’]) && $_SESSION[‘EXPIRES’] < time())
Thanks f᧐r sharing sucһ a pleasant opinion, post is nice,
tһats why i hаᴠe rеad іt fuⅼly
Hi Josh, recently discovered your articles and wanted to
thank you. I am a few months no contact coming out of a 4- year
disaster w a Narcopath attorney who bullied and gaslighted me with absolute calm and detachment.
Personally, I like to hear your personal stories rather than analogies,
but hey- I think you’re great and I am a Texas native.
Keep doin your thing, I appreciate it!
Hi,
Thanks for the Great tutorial! Before implementing this class I had Session hijacking problem with my login system
Now my login system is secured from Session hijacking. With this code, I have couple of issues
Kindly can anyone help on these issues? Thanks in advance
1) While I try to log out session is not destroyed and page is not redirected to index.php
Below is my code in logout.php.
2) PHP Notice: Undefined index: OBSOLETE in /home/XXXXX/public_html/login/include/sec-ses.class.php on line 60
Instead of if(isset($_SESSION[‘OBSOLETE’]) || $_SESSION[‘OBSOLETE’] == true)
I tried by replacing if(isset($_SESSION[‘OBSOLETE’])) warning went off
But since log out was not working I cannot come to a consideration on this fix
Thanks & Regards,
Mohammed
That should be:
if(isset($_SESSION[‘OBSOLETE’]) && $_SESSION[‘OBSOLETE’] == true)
isset AND (&&) ==true
NOT
isset OR (||) ==true
Great article, thanks.
The download link for the “complete Session.class.php file” does not work.
It would be worth also mentioning how to change session id generation from md5 to SHA for high traffic websites since there will be millions of sessions.
Arakawa Under the Bridge : ORE NO T-SHIRT (translation: “My T-shirt”,
think about this being stated in the most Mundane Produced Great
way possible)
I really like your article. What I addititionally wanted to achieve was, to go without writing any internal information into the $_SESSION array and still make the AJAX+Regenerate problem work.
I tried to manage it with an additional database field ‘childID’ where i saved the new session ID, when a regeneration occurred along with the old ID.
But since I had heavy problems with concurrent database queries, altough I worked with row-based locks, I finally thought (after I wasted many hours of time):
Why not just preventing regenerations, when I detect many requests for a session ID within a short amount of time (e.g. 1 second)?
Since I wanted to measure a second or less I added another database field ‘access_micros’ where I save microseconds of the last write access (alternative: MySQL 5.6+ also supports microseconds in date and timestamp functions).
On every session start I now check, if more than a second elapsed. If not, I prevent an ID regeneration.
Now synthetic companies say you can change your oil every 7500 miles and the best synthetic oil will guarantee their oil
to last 12 months and up to 35,000 miles. Motor oil testing using this spectral analysis will also show whether your engine
has a fuel dilution problem. Ground water that is contaminated by only one quart of oil affects up to 250,000 gallons of drinking water.
Keep this going please, great job!|
This is really interesting, You’re a very skilled blogger.
I’ve joined your rss feed and look forward to in the hunt for more of your magnificent post.
Also, I have shared your site in my social networks
Just want to point out that there are few links on this page that no longer work. Also is it still safe to use this post as a reference if there are elements that people are pointing out above and because it is over 5 years old now? I’m new to session management.
looks like in a lot of places it is written “$ SESSION…” when it should be written “$_SESSION…”
it doesn’t work for me either. I read elsewhere that session_start() should be the very first function call in your php script.
True and this class will call session start at every request if you initialize the class correctly, prefably @ the beginning of every php script/page. It offers you a more secure way of handling sessions.
After proper initialization (see tut) you can keep on using sessions like you’ve always done.
I myself use this class for all of my web projects to prevent user sessions from being hijacked and it works just great!
I even attemped to hijack my websites sessions without success and i knew what i was doing.
As long as an attacker doesn’t have acces to the home network of the user than it’s impossible to hijack sessions.
So yes this method of handling sessions is way safer but yet again not bulletproof to social hackers for example with easy access to the network of their prey.
sadas as dasdas asd asdasdsdas dasd
Hi
can someone explain how to use this class? in a login i can save username and password to the session but what do i do when logout?
in addition when i start the session and i set the $limit to 10 the session variables still hold after 10 seconds.
hope someone can explain with good details.
best regards
Would need to take a closer look at the limit problem.
You can initialize the sessionmagager class in every php script/page that needs to work with sessions at the beginning.
On logout you can simply call in your php script: unset($_SESSION);
This wil remove and clear out all sessions for that particular user.
Guys few remarks:
1. $_SERVER[‘remote_addr’] is a CGI variable and it cannot be trusted. If the hacker did fixate the session of the user, then he did communicate with him already. It is very common that he will already have all his CGI headers;
2. Some firewalls block the CGI headers;
3. YOU ARE BLOCKING USERS OF NAT NETWORKS. AOL users for example regularly change their IP’s dynamically. You definitely kick these users out of the system. You DO NOT WANT THAT 🙂
Cheers
Sorry, I take back the last comment I made. The problem is the if statement should be AND instead of OR, like so:-
if ( isset( $_SESSION[‘OBSOLETE’] ) && $_SESSION[‘OBSOLETE’] == true )
return;
The reason being is if $_SESSION[‘OBSOLETE’] is not set then $_SESSION[‘OBSOLETE’] can’t equal true, because it isn’t set.
You should also cover the case when $_SESSION[‘OBSOLETE’] is set to anything else than ‘true’.
I’ve found a bug in the following line of the regenerateSession() function:
if(isset($_SESSION[‘OBSOLETE’]) || $_SESSION[‘OBSOLETE’] == true)
return;
The problem is that if $_SESSION[‘OBSOLETE’] isn’t set, then it will generate Undefined index: OBSOLETE
Best option here is the drop the isset() part of the if statement and instead do the following:
if(@$_SESSION[‘OBSOLETE’] == true)
return;
if( isset( $_SESSION[‘OBSOLETE’] ) || ( isset( $_SESSION[‘OBSOLETE’] ) && $_SESSION[‘OBSOLETE’] == true ) ) {
Great article!
Except you overlooked the vulnerabilities that shared host users are exposed to, session data is stored on files on the server which can be exposed to other users on the same shared host, a good idea would be to store session data in the database.
Another thing PHP has a function which allows you to set your own session handler
bool session_set_save_handler ( callback $open , callback $close , callback $read , callback $write , callback $destroy , callback $gc )
that way you can use the regular PHP session functions instead of calling static class members all the time.
Great Artical, just what i needed
One thing I am not clear about – why the “5% chance of the session id changing on any request”?
Great Article, I was looking for something like this to make site bulletproof.
Good article! I’ve always been stickler for making these things as tough as possible.
One question though. You’ve focused on making the session ID as bulletproof as possible, but what about some good session housecleaning tips like cleaning out important session values on logout or a failed login attempt.
Hi Robert, its not only IE8, ALL the browsers have a kind of compatibility mode. I don’t think its safe to use HTTP_USER_AGENT .
Examples:
IE7:
Initial page: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)
Second page: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Firefox 3:
Initial page: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.13) Gecko/2009073022 Firefox/3.0.13 (.NET CLR 3.5.30729)
Second page: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Firefox 2:
Initial Page: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.20) Gecko/20081217 Firefox/2.0.0.20 (.NET CLR 3.5.30729)
Second Page: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
IE6:
Initial Page: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)
Second page: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Samsung Phone:
Initial page: Samsung-SPHM520 AU-MIC-M520/2.0 MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1
Second page: Mozilla/5.0 (compatible; OpenWeb 5.7.4-09)
And sometimes you can find something like this:
First page: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB6; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)
Second page: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB6; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506),gzip(gfe) (via translate.google.com)
It’s not just AOL proxies – I commute with a laptop, which means my IP address will change from my home WiFi to my 3G dongle to my at-work address all in the space of a couple of hours. I’m not keen on the idea of sites that sign out my session just because I moved from one connection to another. I think my 3G-supplied IP address might change as the train moves from one cell tower to another as well.
I have a principle on dealing with issues such as session management – “keep it simple”.
Every project has different security needs. If the only thing an attacker would possibly be able to do is change an avatar, then stick to the plain session_start().
For other purposes, rely on heavily tested and bug-free session management classes. Don’t start on making it on your own if you are not experienced enough, or you risk countless hours in debugging (or even restoring corrupted databases).
Ditto @Dangerous. IP’s can change on a page by page basis. Browsers, such as Safari & Firefox, will actually send 2 different user agents when checking for RSS feeds. This same half-baked solution has been posted over and over and over. You can’t fix a problem by creating a whole new slew of issues. It’s great for newbs, but no one with any real experience works like this.
Regarding the locking the session to an IP address, just making an exception for AOL won’t cut it. You just can’t really do it in the real world, unless you are perfectly happy for your users to get logged out repeatedly during their session.
And also a note on making session cookies HttpOnly – this can be set in the php.ini.
Thanks, I’ve bookmarked this, found it extremely useful.
nice one, even i’m missing a small walkthrough on the session configuration options/functions like session_cache_expire and especially session_cache_limiter.
regarding the proxy comments: you could the HTTP_X_FORWARDED_FOR / HTTP_CLIENT_IP header to determine if the request was proxied and then use a combination of ip address and user agent instead. also you could check if that IP is inside the private ip network range and maybe even block it then.
I followed through on your advice and have updated the code (http://code.google.com/p/phpsessionmanager/).
The next step will be to extend the class to make the various checks optional. One of the points I was trying to get across with the discussion on cookies and aspects of this was that security issues do depend on the situation, and while some sites may be comfortable disabling some security aspects other sites (or even different sections of a site, such as the admin side of things) may require something a bit tougher.
I’ve updated the SessionManager class and placed it up on google code.
http://code.google.com/p/phpsessionmanager/
The two big changes-
* Session’s are no longer invalidated by IE8 going in and out of compatibility mode
* When the stored and remote IP addresses don’t match a check is done to see if both IP addresses came from AOL proxies.
If someone wanted to expand upon it there are two places they can start-
* Standardize the proxy checks to other networks can use it
* Make the IP checks optional, or less restrictive (instead of a direct match have it work off of the first few segments).
Thanks for all of your input.
I believe web developers shouldnt take IP changes seriously, as long as the cookie is intact within the same session. I start working in gmail using my ISP assigned IP address then I change my PC to a VPN supplied IP address and gmail continues to function correctly regardless of the Ip address change, but there are forums like digitalpoint that immediately log me out when they detect change in IP after I have logged in and used my original Id for some time.
We’ve been comparing User Agents in one of our projects to lock a session to a specific user, but we’ve found that some of our site visitors are failing the check. When they initially visit the site, the user agent is IE 7, but on the next it reads as IE 8. We’ve noticed user agent switching on a few browsers, but IE 8 so far is showing up the most.
Thats really interesting, I hadn’t encountered that type of behavior before. By any chance are you taking advantage of the “compatibility mode” to have IE8 render pages using the ie7 engine? I’m curious as to what can cause this type of issue.
We’re not doing any forcing of user agents or modes. At the moment, we’ve rolled back changes that terminate sessions if user agents don’t match, but are continuing to record and monitor user agents when they change mid-session. In fact, we don’t load any HTML until the very last step. I’ve included one users’ before and after:
Initial page load: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; FunWebProducts; GTB6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
After page redirect: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; GTB6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Believe it or not this is compatibility mode coming back to bite you (even if you didn’t ask for it). When compatibility mode kicks in IE changes its user agent to use a different IE version, but it still uses the “Trident/4.0” tag in the user agent so you know you’re dealing with IE8.
If you edit the “preventHijacking” function above and replace the user agent code with the following it should fix the issue-
if( $_SESSION[‘userAgent’] != $_SERVER[‘HTTP_USER_AGENT’]
&& !( strpos($_SESSION[‘userAgent’], ‘Trident’) !== false
&& strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Trident’) !== false))
return false;
This works by first checking to see if the useragents match, and if not it checks to see if both the stored and incoming useragents are IE8.
Hey tedivm, thanks for that. I’ll include it. That’ll help with this case and since I’ll be listing exceptions like this, I’ll probably create a separate method to check for exceptions.
I’ve been trying to reproduce these errors on my PC but so far have not been able to trigger the switch.
Doug, my reply to your reply to my reply (sorry, couldn’t help that) somehow got put in its own thread. I just wanted to make sure you didn’t miss it.
At a guess, I would say the DOCTYPE headers on both pages differ. Regardless, you can force the page that is causing IE8 agents to drop back to compatibility mode (ie. report as IE7) by including IE’s new X-UA-Compatible META tag which overrides any DOCTYPE header:
Comments munched my META tag.
@Moderator, why are there no CODE blocks allowed in the comments of a blog discussing programming!
The problem occurs when switching from compatibility mode to regular mode (or vice-versa). Its not enough to supply a metadata tag because when IE sees that it appears to reload the page- including resending the changed referrer to the server.
I provided a fix below, which is also at the google code site for the code.
Great tips. Changing the session ID every so often is a good one.
Locking the session ID to a given IP is probably a “Bad(tm)” idea.
If a users network at work or their ISP (such as AOL) filters traffic through a cache filter or a proxy, that might be load balanced in which case the IP can change while going from page to page.
So I’d strongly suggest not doing this 🙂
Nice article,
just a little note on the IP protection as it will not work for AOL customers.
AOL use proxies, and a user can have differents IPs for the same visit.
Regards.
Just checking the ip address like you do is not good, what about people who are behind proxies and change IPs all the time? (AOL, etc)
they will have to login again..
Some people might not agree with me but I really dont like the fact of leaving cookies for more then 1 day on my PC, or even after I close my browser.
Regarding this class… very nice one indeed. All it needs to be really bullet proof is to hash the IP address in MD5 hashes. In short, eliminate “visible” data that the bad guy might see useful.
Awesome article, thanks!
Thats all..
omg
They won’t just have to log in again. It won’t work for them at all. Unless the way AOL works has changed recently, every single request from the same user is likely to come from a different IP. By the time they’ve logged in, they’ll be logged out.