Securing against Uncaught Exceptions

Một phần của tài liệu Tài liệu Learning PHP Data Objects ppt (Trang 80 - 84)

As we have seen previously, we place the try...catch blocks around code that can throw exceptions. However, in very rare cases, there might be some unexpected exceptions. We can imitate such an exception by modifying one of the queries so that it contains some malformed SQL. For example, let's edit authors.php, line 16 to the following:

$q = $conn->query("SELECT * FROM authors ORDER BY lastName, firstName");

Now try to navigate to authors.php with your browser to see that an uncaught exception has occurred. To correctly handle this situation, we either should create an exception handler or wrap every block of code that calls PDO or PDOStatement class methods in a try…catch block..

Let's see how we can create the exception handler. This is an easier approach as it does not require changing lots of code. However, for big applications this may be bad practice as handling exceptions, where they occur may be more secure and better recovery logic can be applied.

However, with our simple application we can use the global exception handler. It will just use the showError() function to say that the site is under maintenance:

/**

* This is the default exception handler * @param Exception $e the uncaught exception */

function exceptionHandler($e) {

showError("Sorry, the site is under maintenance\n" . $e->getMessage());

}

// Set the global excpetion handler

set_exception_handler('exceptionHandler');

Place this into common.inc.php, just before the connection creation code block. If you refresh the authors.php page now, you will see that the handler gets called.

It is always a good idea to have the default exception handler. As you have noticed, unhandled exceptions expose too much sensitive information including database connection details. Also, in real world applications the error pages should not display any information about the type of the error. (Note that our example application does.) The default handler should write to the error log and alert site maintainers about the error.

Summary

In this chapter, we examined how PDO handles errors and introduced exceptions. Also, we investigated the sources of errors and saw how to counter them.

Our sample application was extended with some real-world administration

functionality that uses data validation and is secured against SQL injection attacks.

Of course, they should also allow database modifications only to certain users based on login names and passwords. However, this is beyond the scope of this book.

In the next chapter, we will look at another very important aspect of PDO and database programming in general—using prepared statements. We will see how our administration pages can be simplified with their help, leading to less code and better maintenance.

Prepared Statements

In the previous chapters, we have looked at the basics of PDO, and you may have noticed that most of its functionality resembles the traditional extensions used to connect to databases. The only new thing is exceptions, but even that can be similar to traditional error handling.

In this chapter we will look at a new concept that was not present in PHP before PDO: prepared statements. We will see how they can further simplify our code and even lead to better performance. We will also look at how PDO works with BLOBs—all in a database-independent manner, of course.

Regarding our library management application, we will rewrite the edit/update functionality added in the previous chapter so as to facilitate prepared statements, as well as add support for book cover images, which we will keep in the database..

Prepared Statements

A prepared statement is a template for executing one or more SQL queries against the database. The idea behind prepared statements is that, with queries that use the same syntax but different values, it is much faster to pre-process the syntax once and then execute it several times using different parameters. Consider the following task.

We have to insert the names of several new authors into our database. Of course, we can use command line client or the addauthor page we recently created, but we decide to use a PHP script.

Let's assume that the authors to be added are kept in a PHP array:

$authors = array(

array(

'firstName' => 'Alexander', 'lastName' => 'Dumas',

'bio' => 'Alexandre Dumas was a French writer, best known for hisAlexandre Dumas was a French writer, best known for his numerous historical novels of high adventure which have made him one of the most widely read French authors in the world.'),

array(

'firstName' => 'Ivan', 'lastName' => 'Franko',

'bio' => 'Ivan Franko was a Ukrainian poet, writer, social and literary critic, and journalist. In addition to his own literary work, he translated the works of William Shakespeare, Lord Byron, Dante, Victor Hugo, Goethe and Schiller into the Ukrainian language.'));

This is a two-dimensional array, through which we will iterate using a foreach loop so as to insert both the authors' details into the database.

foreach($authors as $author) {

$conn->query(

'INSERT INTO authors(firstName, lastName, bio) VALUES(' .

$conn->quote($author['firstName']) . ',' . $conn->quote($author['lastName']) .

',' . $conn->quote($author['bio'])')' . );

}

As you can see, we create an SQL statement on each iteration for every author and take care of quoting all the parameters.

With prepared statements, we can construct the query just once and execute it any number of times by just passing different values to it. Our code would then look like this:

$stmt = $conn->prepare('INSERT INTO authors(firstName, lastName, bio) VALUES(?, ?, ?)');

foreach($authors as $author) {

$stmt->execute(

array($author['firstName'], $author['lastName'], $author['bio']));

}

From the above code snippet, you can see that a prepared statement is first prepared by calling the PDO::prepare() method. This method accepts a string containing an SQL command where the values that change are replaced with question mark characters. The call returns an object of class PDOStatement. Then in the loop we call the statement's execute() method rather than PDO::query() method.

The PDOStatement::execute() method accepts an array of values, which are inserted into the SQL query in place of the question marks. The number and order of elements in that array must be same as the number and match the order of question marks in the query template passed to PDO::prepare().

You must have noticed that we don't use PDO::quote() in the code—PDO takes care of proper quoting of the incoming values.

Một phần của tài liệu Tài liệu Learning PHP Data Objects ppt (Trang 80 - 84)

Tải bản đầy đủ (PDF)

(188 trang)