PHP 5 Advanced: Visual QuickPro Guide | Page 2 | WebReference

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:

When to Use Regular Expressions

I 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
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

ctype_alnum()

Letters and numbers

ctype_alpha()

Letters only

ctype_cntrl()

Control characters

ctype_digit()

Numbers

ctype_graph()

Printable characters, except spaces

ctype_lower()

Lowercase letters

ctype_print()

Printable characters

ctype_punct()

Punctuation

ctype_space()

White space characters

ctype_upper()

Uppercase characters

ctype_xdigit()

Hexadecimal numbers

To validate a form

  1. Begin a new PHP script in your text editor or IDE, starting with the HTML (Script 4.1).
  2. 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.

  3. Check for a name.
    A person's name is one of those things that you can use regular expressions on, but it may not be worthwhile. A valid name can contain letters, spaces, periods, hyphens, and apostrophes. Under most circumstances, just checking for a nonempty name is sufficient.
  4. Validate the submitted email address.
    There are any number of patterns you can use to validate an email address, depending on how strict or liberal you want to be. This one is commonly seen. Certainly some invalid email addresses could slip through this expression, but it does add a sufficient level of security. Feel free to use a different pattern if you have one to your liking. Keep in mind that a user could enter a valid e-mail address that does not actually exist. Only some sort of activation process (sending the user an email containing a link back to the Web site) can confirm a real address.
  5. 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.

  6. 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.

  7. Check if the date of birth is a valid date.
    The 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.
  8. Complete the date of birth conditionals.
    The ICQ number can only contain digits, so it makes sense to use the ctype_digit() function.
  9. Check for some comments.
    Comments really cannot be run through a regular expression pattern because any valid pattern would allow just about anything. Instead, a check for some value is made.
  10. If there were no errors, report upon the success.
    If no errors occurred, then $errors would still be empty. The script could then register the user (probably in a database). Here it just prints a message and terminates the script (so that the form isn't redisplayed) instead (Figure 4.2).

    Figure 4.2
    Figure 4.2 If all of the data passed through the various checks, this message is displayed.

  11. Report the errors.
    If $errors isn't empty, it contains all of the fields that failed a validation test. These can be printed in a list (Figure 4.3).

    Figure 4.3
    Figure 4.3 A lot of mistakes were made in this registration attempt, each reported back to the user.

  12. Complete the main conditional and the PHP code.
  13. Create the HTML form.
    There's not much to say about the form except to point out that it does indicate the proper format for the password and date of birth fields. If you are validating data to a specification, it's important that the end user be made aware of the requirements as well, prior to submitting the form.
  14. Complete the page.
  15. Save the file as register.php, place it in your Web directory, and test in your Web browser.

  16. [previous] [next]

    URL: