I spent the last couple of days with coding a new registration module for a private website that I administrate. The requirements were the very basic ones:
- Make an HTML form
- Validate the inputs
- Send a confirmation email with a link
- On link activation: Retrieve the data and write it into a table in the database
As those requirements are common in so many registration forms all over the web, I thought: Before coding something again, just have a look at Google and see if you can find something useful to embed. And I found stuff, lots of stuff but surprisingly every example I found did the following:
- HTML form
- Write data into the table with an “active” column set to false
- Send a confirmation email with an link with an unique identifier for the inserted row (most times a md5 hash value)
- On link activation: Retrieve the unique identifier
- Update the row in the database with active flag set to true
And, at least some examples, took also care about the house keeping and cleaned the inactive rows from time to time.
Well, this does the job of course but the way how it does it is simply dirty – very dirty!
From the functional aspect there are following issues:
- Every SQL statement for retrieving the active data has to make sure to include ” AND active = TRUE” in the WHERE clause
- If an user is unlucky, the cleanup process removes his data before he can click the activation link if the process doesn’t implement a time range
From the performance side however:
All I want to do is:
- Validate the data from the form
- Save it temporarily until the link is clicked or the data gets expired
- Write it into the database
With those solutions found on the internet however I would have done following:
- Validate the data
- Write it into the database (with an column extension for an active flag)
- Retrieve the data again and update it to set it active
- Create a cleanup job to purge inactive data
- Extend all my SQLs against that table with a “AND active = TRUE” WHERE clause
So I have more steps, more unnecessary hops to the database, probably maintain another index over time for the cleanup job. Sometimes I wonder why programmers don’t think first before the code. Of course many roads lead to Rome but that doesn’t mean that you should just take a random one. But as long as there are programmers out there who don’t think or don’t think hard enough there will be always performance problems and people like me needed to solve them. So I guess I shouldn’t complain but my dream of the perfect IT world is still alive…
Well, the webpage in my case is made in PHP which has one nice feature called: Sessions
That does the job perfectly fine and most important: Clean! It is enabled by default, allows you to store data within a session and includes also an expire functionality which is also enabled by default. It supports two ways of storing the session id: Either within a cookie in the browser (enabled by default) or you can also pass the session id over POST and GET requests. As I use a confirmation email to activate the registration I just had to make sure to deactivate the cookie storage feature first as I pass the session id over a link/GET request. I wouldn’t have to deactivate the cookie storage from a functional point of view as the cookie would be just never read again and would expire some time but from security and the “do it right” aspect this has to be deactivated. So all I did was following:
// Disable cookie storage ini_set("session.use_cookies",0); // Start the session session_start(); // Save the data within the session $_SESSION["Title"] = $Title; $_SESSION["FirstName"] = $FistName; $_SESSION["LastName"] = $LastName; //Send the email with the activation link if (mail($Email, "Please activate your registration", "http://www.mywebsite.com/activate.php?sid=".htmlspecialchars (session_id())) { // If sending the mail was successful, store all session data and close the session session_write_close(); } else { // If sending the mail failed, report an error, delete the session data and destroy the session! // Error reporting.... session_unset(); session_destroy(); }
And all the activation.php file does, is:
// Disable cookie storage ini_set("session.use_cookies",0); // Set the session id from GET request session_id($_GET["sid"]); // Start session session_start(); // Get variables $Title = $_SESSION["Title"]; $FistName = $_SESSION["FirstName"]; $LastName = $_SESSION["LastName"]; // Connect to database $hDB = @mysql_connect("localhost", "user","password"); mysql_select_db("myDB", $hDB); // Insert data into database if (mysql_query("INSERT INTO table (Title, FirstName, LastName) VALUES ('".mysql_real_escape_string($Title)."','".mysql_real_escape_string($FirstName)."','".mysql_real_escape_string($LastName)."'") { // Destroy session session_unset(); session_destroy(); }