Приглашаем посетить
Чернышевский (chernyshevskiy.lit-info.ru)

Simple Authentication Schemes

Previous
Table of Contents
Next

Simple Authentication Schemes

The system you will construct in this chapter is essentially a ticket-based system. Think of it as a ski lift ticket. When you arrive at the mountain, you purchase a lift ticket and attach it to your jacket. Wherever you go, the ticket is visible. If you try to get on the lift without a ticket or with a ticket that is expired or invalid, you get sent back to the entrance to purchase a valid ticket. The lift operators take measures to ensure that the lift tickets are not compromised by integrating difficult-to-counterfeit signatures into the passes.

First, you need to be able to examine the credentials of the users. In most cases, this means being passed a username and a password. You can then check this information against the database (or against an LDAP server or just about anything you want). Here is an example of a function that uses a MySQL database to check a user's credentials:

function check_credentials($name, $password)  {
  $dbh = new DB_Mysql_Prod();
  $cur = $dbh->execute("
    SELECT
      userid
    FROM
      users
    WHERE
      username = '$name'
    AND password = '$password'");
  $row = $cur->fetch_assoc();
  if($row) {
    $userid = $row['userid'];
  }
  else {
    throw new AuthException("user is not authorized");
  }
  return $userid;
 }

You can define AuthException to be a transparent wrapper around the base exception class and use it to handle authentication-related errors:

class AuthException extends Exception {}

Checking credentials is only half the battle. You need a scheme for managing authentication as well. You have three major candidates for authentication methods: HTTP Basic Authentication, query string munging, and cookies.

HTTP Basic Authentication

Basic Authentication is an authentication scheme that is integrated into HTTP. When a server receives an unauthorized request for a page, it responds with this header:

WWW-Authenticate: Basic realm="RealmFoo"

In this header, RealmFoo is an arbitrary name assigned to the namespace that is being protected. The client then responds with a base 64encoded username/password to be authenticated. Basic Authentication is what pops up the username/password window on a browser for many sites. Basic Authentication has largely fallen to the wayside with the wide adoption of cookies by browsers. The major benefit of Basic Authentication is that because it is an HTTP-level schema, it can be used to protect all the files on a sitenot just PHP scripts. This is of particular interest to sites that serve video/audio/images to members only because it allows access to the media files to be authenticated as well. In PHP, the Basic Authentication username and password is passed into the script as $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'], respectively.

The following is an example of an authentication function that uses Basic Authentication:

function check_auth()  {
  try {
    check_credentials($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
  }
  catch (AuthException $e) {
    header('WWW-Authenticate: Basic realm="RealmFoo"');
    header('HTTP/1.0 401 Unauthorized');
    exit;
  }
}

Query String Munging

In query string munging, your credentials are added to the query string for every request. This is the way a number of Java-based session wrappers work, and it is supported by PHP's session module as well.

I intensely dislike query string munging. First, it produces horribly long and ugly URLs. Session information can get quite long, and appending another 100 bytes of data to an otherwise elegant URL is just plain ugly. This is more than a simple issue of aesthetics. Many search engines do not cache dynamic URLs (that is, URLs with query string parameters), and long URLs are difficult to cut and pastethey often get line-broken by whatever tool you may happen to be using, making them inconvenient for conveyance over IM and email.

Second, query string munging is a security problem because it allows for a user session parameters to be easily leaked to other users. A simple cut and paste of a URL that contains a session ID allows other users to hijack (sometimes unintentionally) another user's session.

I don't discuss this technique in greater depth except to say that there is almost always a more secure and more elegant solution.

Cookies

Starting with Netscape 3.0 in 1996, browsers began to offer support for cookies. The following is a quote from the Netscape cookie specification:

A server, when returning an HTTP object to a client, may also send a piece of state information which the client will store. Included in that state object is a description of the range of URLs for which that state is valid. Any future HTTP requests made by the client which fall in that range will include a transmittal of the current value of the state object from the client back to the server. The state object is called a cookie, for no compelling reason.

Cookies provide an invaluable tool for maintaining state between requests. More than just a way of conveying credentials and authorizations, cookies can be effectively used to pass large and arbitrary state information between requestseven after the browser has been shut down and restarted.

In this chapter you will implement an authentication scheme by using cookies. Cookies are the de facto standard for transparently passing information with HTTP requests. These are the major benefits of cookies over Basic Authentication:

  • Versatility Cookies provide an excellent means for passing around arbitrary information between requests. Basic Authentication is, as its name says, basic.

  • Persistence Cookies can be set to remain resident in a user's browser between sessions. Many sites take advantage of this to enable transparent, or automatic, login based on the cookied information. Clearly this setup has security ramifications, but many sites make the security sacrifice to take advantage of the enhanced usability. Of course users can set their cookie preferences to refuse cookies from your site. It's up to you how much effort you want to apply to people who use extremely paranoid cookie policies.

  • Aesthetic Basic Authentication is the method that causes a browser to pop up that little username/password window. That window is unbranded and unstyled, and this is unacceptable in many designs. When you use a homegrown method, you have greater flexibility.

The major drawback with using cookie-based authentication is that it does not allow you to easily protect non-PHP pages with them. To allow Apache to read and understand the information in cookies, you need to have an Apache module that can parse and read the cookies. If a Basic Authentication implementation in PHP employees any complex logic at all, you are stuck in a similar situation. So cookies aren't so limiting after all.

Authentication Handlers Written in PHP

In PHP 5 there is an experimental SAPI called apache_hooks that allows you to author entire Apache modules in PHP. This means that you can implement an Apache-level authentication handler that can apply your authentication logic to all requests, not just PHP pages. When this is stable, it provides an easy way to seamlessly implement arbitrarily complex authentication logic consistently across all objects on a site.



Previous
Table of Contents
Next