Index
    Preface
      What This Book Is About
      What You Need to Know
      How This Book Is Organized
      How to Use This Book
      Conventions Used in This Book
      Using Code Examples
      How to Contact Us
      Web Site and Code Examples
      Acknowledgments
      Chapter 1.  Database Applications and the Web
      Section 1.1.  The Web
      Section 1.2.  Three-Tier Architectures
      Chapter 2.  The PHP Scripting Language
      Section 2.1.  Introducing PHP
      Section 2.2.  Conditions and Branches
      Section 2.3.  Loops
      Section 2.4.  Functions
      Section 2.5.  Working with Types
      Section 2.6.  User-Defined Functions
      Section 2.7.  A Working Example
      Chapter 3.  Arrays, Strings, and Advanced Data Manipulation in PHP
      Section 3.1.  Arrays
      Section 3.2.  Strings
      Section 3.3.  Regular Expressions
      Section 3.4.  Dates and Times
      Section 3.5.  Integers and Floats
      Chapter 4.  Introduction to Object-Oriented Programming with PHP 5
      Section 4.1.  Classes and Objects
      Section 4.2.  Inheritance
      Section 4.3.  Throwing and Catching Exceptions
      Chapter 5.  SQL and MySQL
      Section 5.1.  Database Basics
      Section 5.2.  MySQL Command Interpreter
      Section 5.3.  Managing Databases and Tables
      Section 5.4.  Inserting, Updating, and Deleting Data
      Section 5.5.  Querying with SQL SELECT
      Section 5.6.  Join Queries
      Section 5.7.  Case Study: Adding a New Wine
      Chapter 6.  Querying Web Databases
      Section 6.1.  Querying a MySQL Database Using PHP
      Section 6.2.  Processing User Input
      Section 6.3.  MySQL Function Reference
      Chapter 7.  PEAR
      Section 7.1.  Overview
      Section 7.2.  Core Components
      Section 7.3.  Packages
      Chapter 8.  Writing to Web Databases
      Section 8.1.  Database Inserts, Updates, and Deletes
      Section 8.2.  Issues in Writing Data to Databases
      Chapter 9.  Validation with PHP and JavaScript
      Section 9.1.  Validation and Error Reporting Principles
      Section 9.2.  Server-Side Validation with PHP
      Section 9.3.  JavaScript and Client-Side Validation
      Chapter 10.  Sessions
      Section 10.1.  Introducing Session Management
      Section 10.2.  PHP Session Management
      Section 10.3.  Case Study: Using Sessions in Validation
      Section 10.4.  When to Use Sessions
      Section 10.5.  PHP Session API and Configuration
      Chapter 11.  Authentication and Security
      Section 11.1.  HTTP Authentication
      Section 11.2.  HTTP Authentication with PHP
      Section 11.3.  Form-Based Authentication
      Section 11.4.  Protecting Data on the Web
      Chapter 12.  Errors, Debugging, and Deployment
      Section 12.1.  Errors
      Section 12.2.  Common Programming Errors
      Section 12.3.  Custom Error Handlers
      Chapter 13.  Reporting
      Section 13.1.  Creating a Report
      Section 13.2.  Producing PDF
      Section 13.3.  PDF-PHP Reference
      Chapter 14.  Advanced Features of Object-Oriented Programming in PHP 5
      Section 14.1.  Working with Class Hierarchies
      Section 14.2.  Class Type Hints
      Section 14.3.  Abstract Classes and Interfaces
      Section 14.4.  Freight Calculator Example
      Chapter 15.  Advanced SQL
      Section 15.1.  Exploring with SHOW
      Section 15.2.  Advanced Querying
      Section 15.3.  Manipulating Data and Databases
      Section 15.4.  Functions
      Section 15.5.  Automating Querying
      Section 15.6.  Table Types
      Section 15.7.  Backup and Recovery
      Section 15.8.  Managing Users and Privileges
      Section 15.9.  Tuning MySQL
      Chapter 16.  Hugh and Dave's Online Wines:A Case Study
      Section 16.1.  Functional and System Requirements
      Section 16.2.  Application Overview
      Section 16.3.  Common Components
      Chapter 17.  Managing Customers
      Section 17.1.  Code Overview
      Section 17.2.  Customer Validation
      Section 17.3.  The Customer Form
      Chapter 18.  The Shopping Cart
      Section 18.1.  Code Overview
      Section 18.2.  The Winestore Home Page
      Section 18.3.  The Shopping Cart Implementation
      Chapter 19.  Ordering and Shipping at the Online Winestore
      Section 19.1.  Code Overview
      Section 19.2.  Credit Card and Shipping Instructions
      Section 19.3.  Finalizing Orders
      Section 19.4.  HTML and Email Receipts
      Chapter 20.  Searching and Authentication in the Online Winestore
      Section 20.1.  Code Overview
      Section 20.2.  Searching and Browsing
      Section 20.3.  Authentication
      Appendix A.  Linux Installation Guide
      Section A.1.  Finding Out What's Installed
      Section A.2.  Installation Overview
      Section A.3.  Installing MySQL
      Section A.4.  Installing Apache
      Section A.5.  Installing PHP
      Section A.6.  What's Needed for This Book
      Appendix B.  Microsoft Windows Installation Guide
      Section B.1.  Installation Overview
      Section B.2.  Installing with EasyPHP
      Section B.3.  What's Needed for This Book
      Appendix C.  Mac OS X Installation Guide
      Section C.1.  Getting Started
      Section C.2.  Installing MySQL
      Section C.3.  Setting Up Apache and PHP
      Section C.4.  What's Needed for This Book
      Appendix D.  Web Protocols
      Section D.1.  Network Basics
      Section D.2.  Hypertext Transfer Protocol
      Appendix E.  Modeling and Designing Relational Databases
      Section E.1.  The Relational Model
      Section E.2.  Entity-Relationship Modeling
      Appendix F.  Managing Sessions in theDatabase Tier
      Section F.1.  Using a Database to Keep State
      Section F.2.  PHP Session Management
      Section F.3.  MySQL Session Store
      Appendix G.  Resources
      Section G.1.  Client Tier Resources
      Section G.2.  Middle-Tier Resources
      Section G.3.  Database Tier Resources
      Section G.4.  Security and Cryptography Resources
      Appendix H.  The Improved MySQL Library
      Section H.1.  New Features
      Section H.2.  Getting Started
      Section H.3.  Using the New Features
    Colophon
    Copyright



 

Previous Section  < Day Day Up >  Next Section

11.2 HTTP Authentication with PHP

Writing PHP scripts to manage the authentication process allows for flexible authorization logic. For example, an application might apply restrictions based on group membership: a user in the finance department gets to see the reports from the budget database, while others can't. In another application, a user of a subscription-based service might supply a correct username and password, but be denied access when a fee is 14 days overdue. Or, access might be denied on Thursday evenings during Australian Eastern Standard Time when system maintenance is performed.

PHP scripts give you more control over the authentication process than Apache files or configuration. In this section, we show you how PHP scripts can use authentication credentials, and how to develop simple, flexible authentication scripts that use HTTP.

11.2.1 Accessing User Credentials

When PHP processes a request that contains user credentials encoded in the Authorized header field, access is provided to those credentials through the superglobal variable $_SERVER. The element $_SERVER["PHP_AUTH_USER"] holds the username that's supplied by the user, and $_SERVER["PHP_AUTH_PW"] holds the password.

The script shown in Example 11-1 reads the authentication superglobal variables and displays them in the body of the response. In practice, you wouldn't display them back to the user because it's insecure—we've just done this to illustrate how they can be accessed. Instead, you'd use the credentials to authenticate the user, and allow or deny access to the application. We explain how to do this in the next section.

For the PHP code in Example 11-1 to display the authentication credentials, the script needs to be requested after a user has been challenged for a username and password. For example, the challenge can be triggered by placing the script file in a directory configured by Apache to require authentication as discussed in the previous section. The use of the superglobal variables doesn't trigger authentication, it just provides access to the values the user has provided.

Example 11-1. PHP access to authentication
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Authentication</title>

</head>

<body>

<?php

  if (isset($_SERVER["PHP_AUTH_USER"]))

    print "<h2>Hi there {$_SERVER["PHP_AUTH_USER"]}</h2>";

  else

    print "You need to be authenticated for this to work!";



  if (isset($_SERVER["PHP_AUTH_PW"]))

    print "<p>Thank you for your password {$_SERVER["PHP_AUTH_PW"]}!";

?>

</body>

</html>

With access to the authentication header field information, simple applications that rely on identifying the user can be developed. For example, an application that charges on a per-page view basis might use the $_SERVER["PHP_AUTH_USER"] variable when recording an access to a particular page. In this way, Apache can provide the authentication, and the application records the users' behavior.

While this simple approach to developing an application removes the need to write any PHP code to implement authentication, users and passwords need to be maintained in an Apache password file. In the next section, we describe how to manage HTTP authentication from within a PHP script, thus relieving Apache of authentication responsibilities and allowing more complex logic to be applied to request authorization.

11.2.2 Managing HTTP Authentication with PHP

PHP scripts can manage the HTTP authentication challenges. To do this, you check if the variables $_SERVER["PHP_AUTH_USER"] and $_SERVER["PHP_AUTH_PW"] are set. If they're not, the user hasn't been authenticated and you send a response containing the WWW-Authenticate header to the browser. If the variables are set, the user has answered the challenge, and you check them against the credentials stored in the script using any logic that's required. If the user's credentials match those stored in the script, the user is allowed to use the script; if not, the challenge is sent again to the browser.

In Example 11-2, the user credentials are passed to the function authenticated( ) . This function uses the unsophisticated authentication scheme of checking that the password matches one that's hard-coded into the script and, if so, it allows the user to access the application. To test the script, you can use any username and the password kwAlIphIdE (the case is important). The template that's used with the example is shown in Example 11-3.

Example 11-2. A script that generates an unauthorized response
<?php

require_once "HTML/Template/ITX.php";

require "db.inc";



function authenticated($username, $password)

{

  // If either the username or the password are

  // not set, the user is not authenticated

  if (!isset($username) || !isset($password))

    return false;



  // Is the password correct?

  // If so, the user is authenticated

  if ($password == "kwAlIphIdE")

    return true;

  else

    return false;

}



$template = new HTML_Template_ITX("./templates");

$template->loadTemplatefile("example.11-3.tpl", true, true);



$username = shellclean($_SERVER, "PHP_AUTH_USER", 20);

$password = shellclean($_SERVER, "PHP_AUTH_PW", 20);



if(!authenticated($username, $password))

{

  // No credentials found - send an unauthorized

  // challenge response

  header("WWW-Authenticate: Basic realm=\"Flat Foot\"");

  header("HTTP/1.1 401 Unauthorized");



  // Set up the body of the response that is

  // displayed if the user cancels the challenge

  $template->touchBlock("challenge");

  $template->show( );

  exit;

}

else

{

  // Welcome the user now they're authenticated

  $template->touchBlock("authenticated");

  $template->show( );

}

?>

Example 11-3. The template that's used with Example 11-2
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Web Database Applications</title>

</head>

<body>

<!-- BEGIN challenge -->

  <h2>You need a username and password to access this service</h2>

  <p>If you have lost or forgotten your password, tough!

<!-- END challenge -->

<!-- BEGIN authenticated -->

  <h2>Welcome!</h2>

<!-- END authenticated -->

</body>

</html>

The authenticated( ) function returns false if either the $username or $password hasn't been set, or if the password isn't equal to the string kwAlIphIdE. If the user credentials fail the test, the script responds with the header field WWW-Authenticate, and sets the encoding scheme to Basic and the realm name to Flat Foot. It also includes the status code 401 Unauthorized. The PHP manual suggests sending the WWW-Authenticate response line before the HTTP/1.1 401 Unauthorized response line to avoid problems with some versions of the Internet Explorer browser.

The first time a browser requests this page, the script sends the challenge response containing the 401 Unauthorized header field. If the user cancels the authentication challenge, usually by clicking the Cancel button in a dialog box that collects the credentials, the HTML encoded in the challenge response is displayed. When they provide the correct credentials (a username and the password kwAlIphIdE), a welcome message is displayed. If they don't provide the correct credentials and don't press Cancel, the authentication dialog is redisplayed until they do.

11.2.3 Limiting Access by IP Address

Sometimes it's useful to limit access to an application, or part of an application, to users who are on a particular network or using a particular machine. For example, access to administrative functions in an application could be restricted to a single machine, or the latest version of your application could be limited to only those users in the testing department. In PHP, implementing this type of restriction is straightforward: you can check the IP address of the machine from which a request was sent by inspecting the variable $_SERVER["REMOTE_ADDR"]. You can do the same thing in Apache, but we don't discuss that here. (In addition, IP addresses can also be used to help prevent session hijacking, a problem discussed later in this chapter.)

The script shown in Example 11-4 allows access for users who have machines on a particular network subnet. The script limits access to the main content of the script to requests sent from clients with a range of IP addresses that begins with 141.190.17. Because that is just the start of an address, we test just the first 10 characters. The template used with the example is shown in Example 11-5.

Example 11-4. PHP script that forbids access from browsers outside an IP subnet
<?php

require_once "HTML/Template/ITX.php";



$template = new HTML_Template_ITX("./templates");

$template->loadTemplatefile("example.11-5.tpl", true, true);



if(strncmp("141.190.17", $_SERVER["REMOTE_ADDR"], 10) != 0)

{

  // Not allowed

  header("HTTP/1.1 403 Forbidden");

  $template->touchBlock("noaccess");

  $template->show( );

  exit;

}

else

{

  // Allowed

  $template->touchBlock("authenticated");

  $template->show( );

}

?>

Example 11-5. The template used with Example 11-4
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Web Database Applications</title>

</head>

<body>

<!-- BEGIN noaccess -->

<h2>403 Forbidden</h2>

<p>You cannot access this page from outside the Marketing Department.

<!-- END noaccess -->

<!-- BEGIN authenticated -->

<h2>Marketing secrets!</h2>

<p>Need new development team - the old one says <i>No</i> far too often.

<!-- END authenticated -->

</body>

</html>

There are several HTTP status codes that are appropriate to use when denying access to a user. In the previous section, we used the response code of 401 Unauthorized to control HTTP authentication. However, the response status code of 403 Forbidden is more appropriate if an explanation as to why access has been denied is required and this is used in Example 11-4. The HTTP/1.1 standard describes 17 4xx status codes that have various meanings. The infamous 404 Not Found is returned by Apache if the requested resource doesn't exist, and a PHP script can return this code if the exact reason for the refusal needs to be hidden.

11.2.4 Authentication Using a Database

In this section, we show you how scripts can authenticate by querying a database table that contains usernames and passwords. Because users' credentials are sensitive information, we show how to protect passwords with encryption, and how the encrypted password is used in the authentication process.

11.2.4.1 Creating a database and table

To demonstrate the principles of using a database to manage authentication, we need a table that stores usernames and passwords, and we need a user who can access the database and the table. It's important to note that these are two different issues: the database table is used to store the usernames and passwords for the users of our application, while the MySQL database user is just used in our PHP scripts to read and write data to the database. We set up the database, table, and the MySQL account in this section.

In our examples in the remainder of the chapter, we use an authentication database that contains a users table. To create both, you need to log in as the MySQL root user and type the following into the MySQL command interpreter:

mysql> create database authentication;

Query OK, 1 row affected (0.05 sec)



mysql> use authentication;

Database changed

mysql> CREATE TABLE users (

    ->   user_name char(50) NOT NULL,

    ->   password char(32) NOT NULL,

    ->   PRIMARY KEY (user_name)

    -> ) type=MyISAM;

Query OK, 0 rows affected (0.02 sec)

The users table defines two attributes: user_name and password. The user_name must be unique and is defined as the primary key.

It's also necessary to have a MySQL user that has access to this database. You can create a user lucy with a password secret using the following statement, again entered into the MySQL command interpreter:

mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON authentication.users TO

    -> lucy@127.0.0.1 IDENTIFIED BY 'secret';

Query OK, 0 rows affected (0.00 sec)

The syntax of this statement is discussed in Chapter 15. We use the user lucy in our scripts in the remainder of the chapter.

11.2.4.2 Protecting passwords

Storing user passwords as plain text represents a security risk because insiders, external hackers, and others may gain access to a database. Therefore, a common practice is to encrypt the password using a non-reversible, one-way encryption algorithm and store the encrypted version in the database. The encrypted version is then used in the authentication process. (One-way or asymmetric encryption is discussed later in this chapter.)

The process of protecting a password works as follows. First, a new username and password are collected from the user. Then, the password is encrypted and a new row is inserted into the users table that contains the plain text username and the encrypted password. Later, when the user returns and wants to log in to the application, they provide their username and password. The password provided by the user is encrypted, the row is retrieved from the users table that matches the provided username, and the encrypted version of the password supplied by the user is compared to the encrypted version stored in the table. If the username and encrypted passwords match, the credentials are correct and the user passes the authentication.

PHP provides two functions that can be used for one-way encryption of passwords. We define the functions next, and then show you examples that explain their behavior in more detail.


string crypt(string message [, string salt])

On most platforms, this function returns an encrypted string that's calculated with a popular (if somewhat old) encryption algorithm known as DES. The plain text message to be encrypted is supplied as the first argument, with an optional second argument used to salt the DES encryption algorithm. By default, only the first eight characters of the message are encrypted, and the salt is a two-character string used by DES to make the encrypted string harder to crack. PHP generates a random salt if one isn't provided. The first two characters of the returned value is the salt used in the encryption process.

As we show later, a salt is used to help prevent two passwords that are identical being encrypted to the same string. The salt and the password are both inputs to the encryption function and, therefore, when two passwords are the same but have different salts, the output is different. To encrypt another string to test if it's the same as the encrypted string, you need to know what salt was used so that you can re-use it. For this reason, the salt is returned as the first two characters of the encrypted string.

This function is one-way: the returned value can't be decrypted back into the original string.

Several PHP constants control the encryption process, and the default behavior is assumed in the description we've provided. However, on some platforms, the internals of the function actually use the MD5 approach discussed next or the salt can be longer. You should consult the PHP manual for more details.


string md5(string message)

Returns a 32-character message digest calculated from the source message using the RSA Data Security, Inc. MD5 Message Digest Algorithm (http://www.faqs.org/rfcs/rfc1321.html.). A digest is a 32-character fingerprint or signature of a message, and is not an encrypted representation of the message itself. The MD5 message digest is calculated by examining the whole message, and messages that differ by a single character produce very different digest results. Like the crypt( ) function, md5( ) is one-way.

It is impossible to generate the original message from a digest. The digest of the message is always 32 characters, and it's not an encrypted representation of the message. Instead, it's a string that's calculated from the message that is almost guaranteed to be unique to that message.

This function is widely supported on most platforms, and should be used in preference to crypt( ) for code that needs to be portable. Note that MD5 message digests and Apache's Digest authentication are unrelated concepts.

Example 11-6 shows how crypt( ) and md5( ) are used. The script generates the following output:

md5(aardvark7) = 94198c7f71931fdeb0a7f4b75a603586

crypt(aardvark7, 'aa') = aaE/1j3.0Ky/Y

crypt(aardvark7, 'bb') = bbptug8K4z6vA



md5(aardvark8) = 4a68f92613baa5202d523134e768db13

crypt(aardvark8, 'aa') = aaE/1j3.0Ky/Y

crypt(aardvark8, 'bb') = bbptug8K4z6vA

Example 11-6. Using crypt( ) and md5( )
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Passwords</title>

</head>

<body>

<?php

$passwords = array( );

$passwords[] = "aardvark7";

$passwords[] = "aardvark8";



foreach($passwords as $password)

{

  print "\n<p> md5({$password}) = " . md5($password);

  print "\n<br> crypt({$password}, 'aa') = " . crypt($password, "aa");

  print "\n<br> crypt({$password}, 'bb') = " . crypt($password, "bb");

}

?>

</body>

</html>

Both functions have advantages and disadvantages:

  • md5( ) works with strings of any length. It returns a fixed-length string of 32 characters that's different if the input strings are different. It differentiates between aardvark7 and aardvark8 in Example 11-6 as one would expect.

  • crypt( ) uses only the first eight characters of a password and a salt to calculate the encrypted string and so, if the first eight characters and the salt are the same, the encrypted strings are the same. In Example 11-6, it does not differentiate between aardvark7 and aardvark8 when the salt is the same.

  • The salt in crypt( ) adds a useful extra feature that isn't automatically supported by md5( ): when the string is encrypted with a different salt string, it produces a different encrypted text even when two users have chosen the same password. In Example 11-6, the result of encrypting aardvark7 with the salts aa and bb is a very different string.

A common strategy is to use the first two characters of the username as the salt to crypt( ). In general, this results in different encrypted strings even if the users choose the same password, because it's unlikely they'd also have the same first two characters in their username. If you want to salt the md5( ) input, you could pass both the username (or part of the username) and the password to the md5( ) function by concatenating the strings.

The users table has been defined to store the 32-character result of the md5( ) function. The following fragment of code shows how the password is protected using the md5( ) function and a new user is inserted into the users table.

function newUser($connection, $username, $password)

{

  // Create the digest of the password

  $stored_password = md5(trim($password));



  // Insert the user row

  $query = "INSERT INTO users SET password = '$stored_password',

                                  user_name = '$username'";



  if (!$result = @ mysql_query ($query, $connection))

    showerror( );

}

The function expects three parameters: a MySQL database connection that has the authentication database as the selected database, a plain text username, and a plain text password. In the next section, we show you how to authenticate a user by comparing a password that's provided by the user to the stored password. Later in this chapter, we show you how passwords are updated in the users table as part of a complete authentication framework.

Because both crypt( ) and md5( ) are one-way, after a password is stored, there is no way to read back the original value. This prevents desirable features such as reminding a user of his forgotten password. However, importantly, it prevents all but the most determined attempts to get access to the passwords.

11.2.4.3 Authenticating

When a script needs to authenticate a username and password collected from an authentication challenge, it needs to check the credentials against the database. To do this, the user-supplied password is encrypted, and then a query is executed to find a row in the users table that has a matching username and encrypted password. If a row is found, the user is valid.

Example 11-7 shows the authenticateUser( ) function that validates credentials. The function is called by passing in a handle to a connected MySQL server that has the authentication database selected and the username and password collected from the authentication challenge. The script begins by testing $username and $password, and if either variable is not set, the function returns false. The script then constructs a SELECT query to search the users table using $username and the digest of $password created using the md5( ) function. The query is executed and if a row is found, the $username and $password have been authenticated, and the function returns true.

Example 11-7. Authenticating a user against an encrypted password in the users table
<?php



function authenticateUser($connection, $username, $password)

{

  // Test the username and password parameters

  if (!isset($username) || !isset($password))

    return false;



  // Create a digest of the password collected from

  // the challenge

  $password_digest = md5(trim($password));



  // Formulate the SQL find the user

  $query = "SELECT password FROM users WHERE user_name = '{$username}'

            AND password = '{$password_digest}'";



  if (!$result = @ mysql_query ($query, $connection))

    showerror( );



  // exactly one row? then we have found the user

  if (mysql_num_rows($result) != 1)

    return false;

  else

    return true;

}

?>

The authenticateUser( ) function is likely to be used in many scripts, so it's useful to store it in a require file. For example, if the code is stored in the file authentication.inc, we could rewrite Example 11-4 to use the database authentication function by requiring the file. The rewritten version is shown in Example 11-8.

Example 11-8. A rewritten version of Example 11-4 that uses database authentication
<?php

require "authentication.inc";

require "db.inc";

require_once "HTML/Template/ITX.php";



$template = new HTML_Template_ITX("./templates");

$template->loadTemplatefile("example.11-3.tpl", true, true);



if (!($connection = mysql_connect("localhost", "lucy", "secret")))

    die("Could not connect to database");



if (!mysql_selectdb("authentication", $connection))

   showerror( );



$username = mysqlclean($_SERVER, "PHP_AUTH_USER", 50, $connection);

$password = mysqlclean($_SERVER, "PHP_AUTH_PW", 32, $connection);



if (!authenticateUser($connection, $username, $password))

{

  // No credentials found - send an unauthorized

  // challenge response

  header("WWW-Authenticate: Basic realm=\"Flat Foot\"");

  header("HTTP/1.1 401 Unauthorized");



  // Set up the body of the response that is

  // displayed if the user cancels the challenge

  $template->touchBlock("challenge");

  $template->show( );

  exit;

}

else

{

  // Welcome the user now they're authenticated

  $template->touchBlock("authenticated");

  $template->show( );

}

?>

11.2.4.4 Encrypting other data in a database

The PHP crypt( ) and md5( ) functions can be used only to store passwords, personal identification numbers (PINs), and so on. These functions are one-way: after the original password is encrypted and stored, you can't get it back (in fact, as discussed previously, an md5( ) return value is a signature or fingerprint and not an encrypted copy of the message). Therefore, these functions can't be used to store sensitive information that an application needs to retrieve. For example, you can't use them to store and retrieve credit card details or to encrypt a sensitive document.

To store sensitive information, you need two-way functions that use a secret key to encrypt and decrypt the data. One significant problem when using a key to encrypt and decrypt data is the need to securely manage the key. The issue of key management is beyond the scope of this book, however we discuss encryption briefly in Section 11.4.

If you need to store data using two-way encryption, a good set of tools are in the mcrypt encryption library. PHP provides a set of functions that access it but, to use them, you must install the libmcrypt library and then compile PHP with the --with-mcrypt parameter; ready-to-use Microsoft Windows software is also available from the PHP web site. We don't discuss the mcrypt library in this book, but you can find more information at http://www.php.net/manual/en/ref.mcrypt.php and at http://mcrypt.sourceforge.net/.

MySQL also offers the reversible encode( ) and decode( ) functions described in Chapter 15.

    Previous Section  < Day Day Up >  Next Section







    Copyright © 2010 | Domen maybe sale - bye this domen