PHP 5 Advanced: Visual QuickPro Guide | Page 2
[previous] [next]
Security Techniques
Validating Form Data
Handling form data is still far and away the most common use of PHP (in this author's humble opinion, anyway). The security concern lies in the fact that the PHP page handling the form will do something with the information the user enters: store it in a database, pass it along to another page, or use it in an email. If the information the user enters is tainted, you could have a major problem on your hands. As a rule, do not trust the user! Mistakes can happen, either on purpose or by accident, that could reveal flaws in your code, cause the loss of data, or bring your entire system to a crashing halt.
Some good validation techniques are:
- Use the
checkdate()
function to confirm that a given date is valid. - Typecast numbers.
- Use regular expressions to check email addresses, URLs, and other items with definable patterns (see the sidebar).
When to Use Regular ExpressionsI often see what I would call an overuse of regular expressions. You should understand that regular expressions require extra processing, so they shouldn't be used flippantly. Many types of data—comments and addresses being just two examples—really don't have a definable pattern. A regular expression that allows for any valid comment or address would allow for just about anything. So skip the server-intensive regular expressions in such cases.
As a guide, regular expressions may be the most exacting security measure, but they're almost definitely the least efficient and possibly the most problematic. I'm not suggesting you shouldn't use them—just make sure they're really the best option for the data being validated.
As with the basic security techniques already reviewed, the hope is that as a somewhat-experienced PHP programmer, you already know most of these things. To be certain, this next example will present a sample registration form, taking various types of information, which will then be precisely validated. In doing so, I'll make use of a couple of Character Type functions, added to PHP in version 4.3. Listed in Table 4.1, these functions test a given value against certain constraints for the current locale (established by the setlocale()
function).
Figure 4.1 When users first come to the registration page, this is the form they will see.
Table 4.1. The Character Type functions provide validation specific to the given environment (i.e., the locale setting).
Function |
Checks If Value Contains |
|
Letters and numbers |
|
Letters only |
|
Control characters |
|
Numbers |
|
Printable characters, except spaces |
|
Lowercase letters |
|
Printable characters |
|
Punctuation |
|
White space characters |
|
Uppercase characters |
|
Hexadecimal numbers |
To validate a form
- Begin a new PHP script in your text editor or IDE, starting with the HTML (Script 4.1).
Create the section of the script that handles the submitted form.
Your script should always handle the form before it could possibly redisplay it (on errors found). I like to use a hidden form input to check if a form was submitted. The hidden form input will always be passed to the page upon submission, unlike any other input (on Internet Explorer, if a user submits a button by pressing Enter, then the submit button won't be set).
One way I like to validate forms is to use an array that stores the errors as they occur. By checking if this array is empty, the script can tell if all validation tests have been passed. If the array isn't empty, its values can be used to print the error messages.
- Check for a name.
- Validate the submitted email address.
Validate the submitted password.
The form indicates that the password must contain only letters and numbers. To validate such values, the function
ctype_alnum()
works perfectly.In a real registration form, I would also recommend confirming the password with a second password input, then making sure both values match. I'm skipping that step here for brevity's sake.
Begin checking to see if the user entered a valid date of birth.
There is really no way of knowing if the information users enter is in fact their birthday, but PHP's built-in
checkdate()
function can confirm whether or not that date existed. Since the form takes the date of birth as a simple string in the format MM/DD/YYYY, the script must first confirm that something was entered. I also check if the string's length is at least eight characters long (e.g., 1/1/1900) but no more than ten characters long (e.g., 12/31/2000).This string is then exploded on the slashes to theoretically retrieve the month, day, and year values. Next, a conditional checks that exactly three parts were created by the explosion.
- Check if the date of birth is a valid date.
checkdate()
function confirms that a date is valid. You might want to also check that a user didn't enter a date of birth that's in the future or the too-recent past. Each value is typecast as an integer as an extra precaution. - Complete the date of birth conditionals.