Cookies: Fresh From Your Browser's Oven
by Glenn Fleishman
One Per Person, Please!
Often, in conducting polls, contests, or other kinds of form-based entries, you want to provide a per-user limit. You could do this by requiring an e-mail address, but users can certainly enter any kind of garbage they want for e-mail. If you add a requirement to send e-mail with a code before they can fill out the form, you'll ensure uniqueness, but this won't especially encourage entry, unless you're giving away money.
Using a simple cookie script, you can avoid this whole issue by providing a per-browser limit. This breaks down only when a user comes upon a shared machine. I try to always provide backup schemes to track an event in case the expected client variable isn't there. In this case, a combination of the remote host's IP address and browser variable is the second method.
To ensure the user has the cookie, the poll or other form input page should probably be a no-parse header (NPH) script (see "No-Parse Headers") so you can ensure that a cookie will be sent via the HTTP header before it reaches the form-processing component. The easiest way to do this is to create an HTML file stored in a regular directory and have the NPH script in cgi-bin or another executable path. Through a GET request as part of the URL linking to the form, you feed the location and other details.
A few lines of code on the processing side can confirm the passing of the cookie. Figure 1 shows the bare bones of what's needed, and it assumes you're doing some kind of form recording with one record per line. It also assumes that your cookie is unique.
One of the most annoying things about visiting a site that requires registration is remembering usernames and passwords. Some very secure sites use combinations of SecurID or related password generators, encrypted persistent passwords, and questions about personal preferences to ensure that the right person is at the other end. I don't propose that all users get SecurID, but wise use of personal bits — with the user's knowledge — along with cookies can reduce the hassle.
First off, when you complete the registration, you should assign a very long-lived cookie, with an expires setting of as far as "31-Dec-99 GMT". You can always reset the cookie later. You may also want to limit use of the cookie to a secure connection, in which case you include the word "secure" in the Set-Cookie header.
Since the cookie file isn't encrypted locally, even with the secure setting, you'll want to install other checks and balances as well. At registration, you might want to ask someone odd but memorable information that they wouldn't consider too personal, but that would be private. Shoe size, height, or the city their mother was born in would be unique, would provide a variety of potential values, and wouldn't be considered privileged information to most people. However, you should avoid asking for someone's mother's maiden name. So many credit card companies and financial firms use this obscure bit of information as a common security check that it has become highly privileged, and you might not want to make people nervous or take the risk involved in maintaining that data.
The cookie should be a uniquely generated number or code that can be used later. If you're using some kind of internal site-tracking code, you could set that as the ID as well.
Here's some psuedo-code that could be used to confirm return visitors:
Have they fed a cookie to the server?
If so, do I have a record corresponding to it?
Yes: look up the record.
Check the browser variable. Are they using the same browser (for the cookie to be the same, they have to, so fail login if a different browser)?
Check the IP number. Is the Class A, B, or C range the same?
Check the duration between now and their previous login.
If the IP range is correct and the duration is low, ask them for one random bit of information; if not, ask for two.
Failure to answer correctly dumps the user back into the registration system. (Or more questions could be asked.)
No: ask them if they've registered before. If so, ask them for three pieces of information.
If they answer correctly, feed out the cookie again that was stored for the appropriate user. Otherwise, dump them into new registration.
If they haven't registered before, create a record, feed out a cookie, and go through the registration process.
Depending on the kind of information on the protected site, you could bypass any questions and allow cookies of the right kind to let people right in — even to the extent of using a checksum or some other method that doesn't involve storing cookies in a database.
Me Want Cooookie!
By the way, I couldn't find any reference to why a cookie is called a cookie, and we'd all like to know, I'm sure. The Hacker's Dictionary gives a prosaic definition; anyone knowing the real history of the term's coining, please e-mail details and sources.
Consumer-site owners have ever-increasing pressure to gather more information about usage patterns and users, as they attempt to provide more focused demographics and statistics to advertisers. Those outside the race for dollars can rejoice in gathering more focused information from their users based on their interests, or at least save them the chore of entering and re-entering the details of their lives.