Form security is a top priority these days due to the risks of losing sensitive information, getting spammed by bots, being exposed to viruses, and more. As a result, it is important to take steps to secure your forms in order to counter these risks.

In this article, we’re going to create a PHP class to help secure forms with basic math questions. This class will generate two random numbers that must be added by the user in order to ensure a human is submitting the form. Taken as a whole, this class only takes about 10 minutes to write. This begs the question: are you willing to secure your forms for a few minutes of work?

This PHP class, which will be called BasicMathSecurity, will have three main functions:

  • generateNumbers – generates two random numbers from 1-9 that the user must add
  • getField – returns the label and input tags that will be displayed
  • isCorrect – checks whether the user input is correct

Before we begin with these functions, let’s write a simple constructor:

public function BasicMathSecurity( $name = 'math' )
{
	$this->name = $name;
	$this->generateNumbers();
}

$name will be the name of the user input field. Note that generate numbers is called during instantiation to eliminate the need for an extra call.

generateNumbers is trivial through the use of PHP’s mt_rand function:

public function generateNumbers()
{
	$this->operand1 = mt_rand( 1, 9 );
	$this->operand2 = mt_rand( 1, 9 );
}

getField will create three HTML tags:

  • A label for the math field with the question (ex. “1 + 1 =”)
  • The math field, which is a text input
  • A hidden input field for the answer to the math question

Using the $name paramater asked for in the constructor, the following function can be produced:

public function getField()
{
	$label = '<label for="' . $this->name . '">' . $this->operand1 . ' + ' . $this->operand2 . ' = </label>';
	$math = '<input type="text" name="' . $this->name . '" value="" id="' . $this->name . '"></input>';

	$answer = '<input type="hidden" name="' . $this->name . '-answer" value="' . ( $this->operand1 + $this->operand2 ) . '"></input>';
	$string = $label . "\n" . $math . "\n" . $answer;

	return $string;
}

An id is added to the math field for styling purposes. In addition, note that the answer field uses the same name as the math field with a “-answer” appended to it. This is important for the next function.

Finally, the isCorrect function will use the global $_REQUEST array to check whether the user input matches the answer:

public function isCorrect()
{
	$answer = $this->name . '-answer';
	if( !isset( $_REQUEST[ $this->name ] ) || !isset( $_REQUEST[ $answer ] ) )
		return false;

	return (int) $_REQUEST[ $this->name ] == (int) $_REQUEST[ $answer ];
}

The $answer index is based off the code in the getField function.

As a whole, the class is as follows:

class BasicMathSecurity {

	private $name;
	private $operand1, $operand2;

	public function BasicMathSecurity( $name = 'math' )
	{
		$this->name = $name;
		$this->generateNumbers();
	}

	public function generateNumbers()
	{
		$this->operand1 = mt_rand( 1, 9 );
		$this->operand2 = mt_rand( 1, 9 );
	}

	public function getField()
	{
		$label = '<label for="' . $this->name . '">' . $this->operand1 . ' + ' . $this->operand2 . ' = </label>';
		$math = '<input type="text" name="' . $this->name . '" value="" id="' . $this->name . '"></input>';

		$answer = '<input type="hidden" name="' . $this->name . '-answer" value="' . ( $this->operand1 + $this->operand2 ) . '"></input>';
		$string = $label . "\n" . $math . "\n" . $answer;

		return $string;
	}

	public function isCorrect()
	{
		$answer = $this->name . '-answer';
		if( !isset( $_REQUEST[ $this->name ] ) || !isset( $_REQUEST[ $answer ] ) )
			return false;

		return (int) $_REQUEST[ $this->name ] == (int) $_REQUEST[ $answer ];
	}

}

To use it, construct a BasicMathSecurity object and display the field:

$math = new BasicMathSecurity( 'math' );
echo $math->getField();

Subsequently, in your form handler, check if the input is correct. Remember to construct the object with the same name parameter:

// construct the object with the same parameter
$math = new BasicMathSecurity( 'math' );
if( $math->isCorrect() ) {
	// process the form
}

And that’s it! You may view the demo and download the files used to create it.

Leave a Reply

Prevent Form Attacks with Basic Math Security