Article

The PHP Anthology Volume 2, Chapter 1 - Access Control

Page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Next

Towards the end of the script appears the code that inserts a value into the signup table and, if all went well, sends the confirmation email:

Example 1.23. 6.php (excerpt)        
       
 // If the form is submitted...        
 if ($form->validate()) {        
   // Apply the encryption filter to the password        
   $form->applyFilter('password', 'encryptValue');        
           
   // Build an array from the submitted form values        
   $submitVars = array(        
       'login' => $form->getSubmitValue('login'),        
       'password' => $form->getSubmitValue('password'),        
       'email' => $form->getSubmitValue('email'),        
       'firstName' => $form->getSubmitValue('firstName'),        
       'lastName' => $form->getSubmitValue('lastName'),        
       'signature' => $form->getSubmitValue('signature')        
   );        
           
   // Create signup        
   if ($signUp->createSignup($submitVars)) {        
     // Send confirmation email        
     if ($signUp->sendConfirmation()) {        
       $display = 'Thank you. Please check your email to ' .        
                  'confirm your account';        
     } else {        
       $display = 'Unable to send confirmation email.<br />' .        
                  'Please contact the site administrators';        
     }        
   } else {        
     $display = 'There was an error creating your account.' .        
                '<br />Please try again later or ' .        
                'contact the site administrators';        
   }        
 } else {        
   // If not submitted, display the form        
   $display = $form->toHtml();        
 }        
}

The finished registration form now looks like the one shown in Figure 1.2.

1279_fig2
Figure 1.2. Sign on the Dotted Line

Missing Pieces

So that you don't get bored, there are a couple of remaining pieces for you to fill in. Currently, the createSignup method triggers an error if there already exists a registered user with the login name or email provided by the new registrant. If you're happy with QuickForm, you might want to split this check into a separate method that QuickForm can apply as a rule for each field in the form. This should reduce frustration when users find that the account name they chose already exists; QuickForm will generate a message to tell them what they did wrong, while preserving the rest of the values they entered.

If you plan to let users change their email addresses once their accounts are created, you'll also need to confirm the addresses before you store them against the appropriate records in the user table. You should be able to reuse the methods provided by the SignUp class for this purpose. You might even consider reusing the signup table to handle this task; some modifications will be required to have the confirm/ method check to see if a record already exists in the user table, and if so, update it instead of creating a new row. Be very careful that you don't create a hole in your security, though. If you're not checking for existing records in the user table, a user could sign up for a new account with details that matched an existing row in the user table. You'll then end up changing the email address of an existing user to that of a new user, which will cause some embarrassing moments at the very least.

How do I protect my site from auto sign ups?

I hope you'll never suffer the misfortune of having someone try to put your site out of action, but when you expose your application to what is, after all, a global network, you need to be prepared for trouble. It's difficult to prevent malicious attacks against your site and still offer genuine users an acceptable service—particularly if a malicious user simply decides to flood your site with requests for pages.

Where user registration systems are concerned, one common method of attack has been to create "robots" (typically Perl or PHP scripts), which act as Web browsers and use the forms you've built for your registration system to swamp your database with false sign ups. Although we've built a registration system that requires email confirmation of the account, the confirmation process can also be built into the "robot," assuming it has access to the account to which the email confirmations are sent. Both Hotmail and Yahoo!, among many others, have been stung by this in the past.

The next level of protection is to introduce a mechanism that sorts the men from the 'bots! Thankfully, the human brain is still vastly more powerful than a computer (at least, the sort of computer likely to be used to attack your site) and is capable of powerful optical character recognition beyond the scope of your average Perl script. Consider Figure 1.3, for example.

1279_fig3
Figure 1.3. Humans Still Have the Edge

Now, you and I can see that the image contains the characters "PKPBPI30," but a computer program trying to identify those letters will find the challenge a lot more difficult. Of course it's possible, but people who have the capability to do it will, I hope, have better things to do with their time.

Here's One I Wrote Earlier

Let's turn to a handy PHP class I've prepared to solve just this problem:

Example 1.24. Images/RandomImageText.php (in SPLIB) (excerpt)        
       
<?php        
/**        
* RandomImageText<br />        
* Generate image text which is hard for OCR programs to        
* read but can still be read by humans, for use in registration        
* systems.        
* @package SPLIB        
* @access public        
*/        
class RandomImageText {        
 /**        
  * The background image resource        
  * @access private        
  * @var resource        
  */        
 var $image;        
       
 /**        
  * Image height in pixels        
  * @access private        
  * @var int        
  */        
 var $iHeight;        
       
 /**        
  * Image width in pixels        
  * @access private        
  * @var int        
  */        
 var $iWidth;        
       
 /**        
  * Font height in pixels        
  * @access private        
  * @var int        
  */        
 var $fHeight;        
       
 /**        
  * Font width in pixels        
  * @access private        
  * @var int        
  */        
 var $fWidth;        
       
 /**        
  * Tracks the x position in pixels        
  * @access private        
  * @var  int        
  */        
 var $xPos;        
       
 /**        
  * An array of font idenfiers        
  * @access private        
  * @var array        
  */        
 var $fonts;        
       
 /**        
  * RandomImageText constructor        
  * @param string relative or full path to background jpeg        
  * @param int font height to use        
  * @param int font width to use        
  * @access public        
  */        
 function RandomImageText($jpeg, $fHeight = 10, $fWidth = 10)        
 {        
   $this->image = ImageCreateFromJPEG($jpeg);        
   $this->iHeight = ImageSY($this->image);        
   $this->iWidth = ImageSX($this->image);        
   $this->fHeight = $fHeight;        
   $this->fWidth = $fWidth;        
   $this->xPos = 0;        
   $this->fonts = array(2, 3, 4, 5);        
 }

The class needs to be provided with a JPEG image that will become the background over which we'll scatter the letters. Ideally, you should use an image that has some kind of pattern on it, to make the problem of identifying the letters even more difficult. The $fHeight and $fWidth (font height and width) can be adjusted, but this really only impacts the space that appears around the characters, rather than increasing the size of the characters themselves.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links