Tag Archives: Form

Validating user input with PHP: methods, data, and its applications

If you’ve ever read any kind of article that talks about sanitizing, filtering, cleaning, escaping, or validating user input, I’m sure you’ve come across this line: don’t trust itever! Before you can protect yourself from unwanted data, injections, script crashes, and the like, you’d be smart to follow the next three steps to ensure that you understand the methods, data, and its applications.

  1. Identify all areas that allow for user input. In other words, what can the user manipulate? It’s not necessarily just the form field you provided for them to fill out, but maybe a piece of data that you’re passing in via a query string, a hidden form field, or a browser header.
  2. Determine what is valid input. The more specific you are in asking for a piece of data, the more granular you can be when it comes to validating. For example, instead of loosely asking for an address, you’d ask for the street, city, state, and zip code, which allows you to validate each piece of data separately.
  3. Understand how you’re going to use that data. Whether you display it back on the screen, pass it to another program, or simply store it in a database, each application has its specific needs and requirements. For example, if you display data with HTML code on the screen, you won’t see the code, you’ll see the rendered version — which may or may not be desired — but if you’re storing this data in the database, you’d be OK.

After you’ve asked yourself those questions and thought about your data, you’ll have a good idea on where to start, but just knowing the concept won’t help you with implementation, so let’s take a closer look at each of these.

1. Identify all areas that allow for user input

There are a lot of places a user can change your data, so the best way to look at it is so: if you’re using a piece of data that you did not create and are not in control of every step of the way, you need to validate it. As a side note, filtering, validating, and escaping data are technically speaking three different things, but for simplicity sake, when I refer to validatation, I’m really refering to some or all of those aspects.

Let’s take a look at how you might receive user controllable data:

  • Form fields: these are the most obvious of all, because you’re directly asking the user for data.
  • Hidden form fields: even though the average user doesn’t see those fields, anyone can easily alter the contents of them. So make sure to double check that data before you use it and verify that your script gracefully halts if that piece of data is missing or invalid.
  • Cookies: if you ever store data in a cookie, you need to double check that the value inside has not been altered and doesn’t contain anything that might cause your script to break.
  • Query strings: if your application relies on reading information from the URL, you also need to check that the values you grab are valid. If you’re using a value as an ID number to make a database query, it’s a good idea to ensure that the value truly consists of digits.
  • JavaScript: on occasion you may use JavaScript on your page to pass in a query string or POST data to your script, so keep that in mind before using that particular data.
  • Browser headers: sometimes an application uses information from the user’s browser, such as the referer or user agent, so it’s important to remember that this data can be manipulated as well.
  • Responses: if your script receives data from other applications or servers that you don’t control, that would also be considered user input. For example, maybe you’re parsing an RSS feed or work with JSON reponses.

Checking the above does several things for you:

  • It reduces the risk of your application being used for illicit purposes e.g. compromising your database or sending spam email.
  • It provides you with more control over the data that enters your system e.g. ensuring that a phone number is really a phone number.
  • It allows you to be more efficient in processing the data e.g. if you look up a product in the database via its ID number, but you notice the ID number consists of letters as apposed to a number, there’s no need to make a database query in the first place.

2. Determine what is valid input

This is a pretty tricky subject, because if you’re too specific, you might miss a scenario where perfectly valid data is rejected, but if you’re too unrestrictive, you’ll get data that’s not useful. Some of the things you can control are the length of characters — you should always set a limit — ranges e.g. a number between zero and fifty, and their data type e.g. a number or a string. You can validate input by using some of PHP‘s built-in functions like is_int, ctype_alpha, ctype_alnum, or something more custom like a regular expression or a user-defined function.

In addition, there are two approaches to validating user input: inclusive and exclusive. Inclusive means that you specifically tell your application what is acceptable input, and exclusive let’s you specify the kind of data you don’t want.

An inclusive example would be to say that you want a number greater than zero, but less than fifty. You’re telling the system what to expect. The exclusive version would state that a number less than zero or greater than fifty is unacceptable. Here you told the system what to prevent. A different example would be checking that a phone number consists of only digits, parenthesis, or hyphens (inclusive) versus ensuring that the phone number doesn’t contain any letters or other symbols (exclusive).

Most of the time you’ll probably end up using a combination of the two, depending on whichever scenario is easier to test.

3. Understand how you’re going to use that data

Here are several ways your data can be used and what the best practices are for working with such data:

  1. Database: if you’re planning on storing the data in a database, you need to escape it. Different database languages may have different ways of escaping, so pay attention to which one you’re using, but for MySQL, which is a popular and open source relational database management system (RDBMS), any data must pass through the mysql_real_escape_string() PHP function. It protects your database from injections.
  2. Display: if you’re going to display user supplied data on your website, you should pass it through PHP’s htmlspecialchars() function. It protects your website from cross-site scripting (XSS).
  3. URL: it’s possible that you need to send or save data from a user in the URL. If that’s the case, everything should pass through the urlencode() PHP function. This ensures that your URL remains valid.
  4. Files: perhaps you’re saving information in a log file. Generally speaking, you can store it anyway you want, but if you know which method you’ll be using to read that data, you should store it accordingly. If the file’s contents will be displayed on the screen, use method #2 described above.
  5. Transmission: sometimes you may be sending data from one server or application to another. You should validate your data before transmission appropriately and if you’re on the receiver’s end, you should validate it again to ensure that it hasn’t been modified somewhere in between. It’s similar to the concept of loose coupling, where each system is unaware of what the other system is doing, therefore you can’t assume that it has been validated on the other end.

The purpose of this article was to give you an idea of the methods, data, and its application in systems. There are exceptions to every rule, but now that you know what’s possible and how things are commonly utilized, you have the knowledge to take that and apply it to your own specific project.

If you have suggestions or questions, feel free to leave comments below.

Hybrid form validation: security of server-side (PHP) with efficiency of client-side (jQuery)

Preface

I’ve built a lot of forms in my day, and to be honest, it’s not one of my favorite things to do. The designing and building aspect is fun, but the validation and error reporting, ehh. We all know that server-side validation is a must, and technically speaking, client-side validation optional, but if you love your users, you’ll do it anyway. The challenge then for you, as the web developer, is to vigorously ensure that the client-side (jQuery) and server-side (PHP) validation are identical, so you don’t have discrepancies that confuse your users. The reason client-side validation makes users happy, is because the errors pop up right away and the page doesn’t need to be reloaded.

What if you could trade the pain of writing a client-side validation script with making  server-side validation instantaneous? Yes, AJAX comes to mind, however, the one thing people tend to do with that is display all the errors grouped together, because the AJAX response either updates or adds a div below or above the form, making the user have to figure out which error belongs to which field.

Project

The goal is to validate forms in the most efficient and user-friendly way, without having to compromise speed or security.

Requirements

  • Completely omit client-side validation
  • Display errors instantaneously next to corresponding fields
  • Prevent the page from being refreshed

Solution

The user fills out a form and it gets submitted via jQuery. If the submission takes just a bit longer, a processing message will appear. A separate processing script will validate each field and upon error, store that error in an array using the field’s label as the array item’s key and the error as the array item’s value. At the end of the validation, it will send the form back by calling the form’s function — a user-defined PHP function — with the error array as an argument. jQuery then replaces the existing form on the page with a new form that displays the errors underneath each field. jQuery’s on event handler then ensures that the replaced form is re-submittable.

Implementation

Below is the user-defined PHP function that creates the HTML form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Returns a login form
// @param (array) errors [optional]
// @return (string) login form
function getLoginForm($errors = false) {
    $output .= '<form action="#" name="login" method="post">';
        $output .= '<h2>Sign in to ' . APPNAME . '</h2>';
        $output .= '<div class="field">';
            $output .= '<label for="username">Username</label>';
            $output .= '<input type="text" id="username" name="username" autofocus="autofocus"' . getPostValue('username')  . ' />';
            if(isset($errors['username'])) {
                $output .= '<div class="help">' . $errors['username'] . '</div>';
            }
        $output .= '</div>';
        $output .= '<div class="field">';
            $output .= '<label for="password">Password</label>';
            $output .= '<input type="password" id="password" name="password"' . getPostValue('password')  . ' />';
            if(isset($errors['passsword'])) {
                $output .= '<div class="help">' . $errors['username'] . '</div>';
            }
        $output .= '</div>';
        $output .= '<div class="message"></div>';
        $output .= '<div class="button">';
            $output .= '<button type="button" name="commit" disabled="disabled">Login</button>';
        $output .= '</div>';
    $output .= '</form>';
    return $output;
}
// Returns a login form
// @param (array) errors [optional]
// @return (string) login form
function getLoginForm($errors = false) {
	$output .= '<form action="#" name="login" method="post">';
		$output .= '<h2>Sign in to ' . APPNAME . '</h2>';
		$output .= '<div class="field">';
			$output .= '<label for="username">Username</label>';
			$output .= '<input type="text" id="username" name="username" autofocus="autofocus"' . getPostValue('username')  . ' />';
			if(isset($errors['username'])) {
				$output .= '<div class="help">' . $errors['username'] . '</div>';
			}
		$output .= '</div>';
		$output .= '<div class="field">';
			$output .= '<label for="password">Password</label>';
			$output .= '<input type="password" id="password" name="password"' . getPostValue('password')  . ' />';
			if(isset($errors['passsword'])) {
				$output .= '<div class="help">' . $errors['username'] . '</div>';
			}
		$output .= '</div>';
		$output .= '<div class="message"></div>';
		$output .= '<div class="button">';
			$output .= '<button type="button" name="commit" disabled="disabled">Login</button>';
		$output .= '</div>';
	$output .= '</form>';
	return $output;
}
  • On line 4 you see the optional argument. The variable is set to false so that PHP doesn’t complain when the function is called without a parameter.
  • On line 6 I’m using a named constant to display what the user is logging into. You could replace that with static text.
  • On line 9 I have another custom function called getPostValue() that basically escapes the user’s input before displaying it inside the field.
  • On line 10 we’re checking to see whether an array item with a key, that matches the field’s label, exists. If it does, we know to display an error, if not, that whole help div container is omitted.

Here is how the rendered form looks like in HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="init">
    <form action="#" name="login" method="post">
        <h2>Sign in to SME</h2>
        <div class="field">
            <label for="username">Username</label>
            <input type="text" id="username" name="username" autofocus="autofocus" />
        </div>
        <div class="field">
            <label for="password">Password</label>
            <input type="password" id="password" name="password" />
        </div>
        <div class="message"></div>
        <div class="button">
            <button type="button" name="commit" disabled="disabled">Login</button>
        </div>
    </form>
</div>
<div class="init">
	<form action="#" name="login" method="post">
		<h2>Sign in to SME</h2>
		<div class="field">
			<label for="username">Username</label>
			<input type="text" id="username" name="username" autofocus="autofocus" />
		</div>
		<div class="field">
			<label for="password">Password</label>
			<input type="password" id="password" name="password" />
		</div>
		<div class="message"></div>
		<div class="button">
			<button type="button" name="commit" disabled="disabled">Login</button>
		</div>
	</form>
</div>
  • On line 1 we need to wrap the form in a div, so we can later monitor it with jQuery. What happens is that jQuery will replace the entire form with one that shows the errors. Because that new form is a new object to the page, jQuery doesn’t know about it. It needs a fixed element on the page, such as the init div, whose contents it can monitor.
  • On line 2 you’ll notice that the action attribute is empty. This particular project requires users to have JavaScript turned on, but if you expect users without JavaScript, it’s a good idea to enter the path of the processor,.
  • On line 12 we will show a message to the user when the button gets clicked, so they know the form is processing.
  • On line 14 you’ll notice that I used the button tag to render a button as apposed to the classic <input type=”submit”>. I do that simply so I can style my text fields without having to worry that it will affect my buttons. My button is by default disabled and I then enable it with JavaScript, that way if JavaScript is turned off, the form can’t be submitted. Lastly, my button is of type=”button”, which by default doesn’t do anything (I assign an event handler with jQuery later). You’d make it of type=”submit” if you wanted that button to work without JavaScript.

Below is the jQuery that is in charge of submitting the form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$(document).ready(function(){
 
    initBinding();
 
    // Send any form to its specific processor
    $('body').on('submit', 'form', function(e){
        var form = $(this);
        form.find('button[name=commit]').attr('disabled', 'disabled');
        form.find('.message').delay(100).queue(function() {
            $(this).html('<div class="pending">Sending your request... please wait...</div>');
        });
        $.post('process.php?p=' + form.attr('name'), form.serialize(), function(response) {
            form.parent('div').html(response);
            initBinding();
        });
        e.preventDefault();
    });
 
    function initBinding() {
        // Enable the form's submit button and assign event handler
        $('button[name=commit]').removeAttr('disabled').click(function() {
            $(this).trigger('submit');
        });
    }
 
});
$(document).ready(function(){

	initBinding();

	// Send any form to its specific processor
	$('body').on('submit', 'form', function(e){
		var form = $(this);
		form.find('button[name=commit]').attr('disabled', 'disabled');
		form.find('.message').delay(100).queue(function() {
			$(this).html('<div class="pending">Sending your request... please wait...</div>');
		});
		$.post('process.php?p=' + form.attr('name'), form.serialize(), function(response) {
			form.parent('div').html(response);
			initBinding();
		});
		e.preventDefault();
	});

	function initBinding() {
		// Enable the form's submit button and assign event handler
		$('button[name=commit]').removeAttr('disabled').click(function() {
			$(this).trigger('submit');
		});
	}

});
  • On line 3 I’m calling a function that enables my disabled submit button and assigns a click event to it, so it can submit the form, since my button doesn’t natively do that.
  • On line 6 we’re using jQuery’s on event handler, which basically monitors the HTML body and looks for changes in a form element. This is important so that the form can be resubmitted. When the form gets replaced, it’s an unknown object on the page, however, since jQuery is monitoring it, it will convert the newly replaced form to a submittable form.
  • On line 8 I’m disabling the button, so while the form is processing, it can’t be submitted a second time.
  • On line 9 you’ll notice that we delay the “processing” message slightly, because if it submits right away, there’s no reason to flash it on the screen, but if it takes a bit longer, the user should know that something is happening.
  • On line 12 is where we actually post the form. I’m sending it to process.php, which contains a switch control structure that receives the form attribute’s name, so that the processor knows which fields to expect and validate.
  • On line 14 I’m calling initBinding() again, so that the newly replaced form’s submit button will be re-enabled and can submit again.

Conclusion

You get an easily maintainable and secure form for which you don’t have to write any client-side validation. The form is submitted via jQuery, which doesn’t require the page to be reloaded, and the validation appears almost instantaneous to the user, just as if you had used client-side validation.

If you have any questions or suggestions, please feel free to leave comments below.