Listing 5-1 (Continued) $this->status = TRUE; $this->user_id = $row->USER_ID; } else { $this->status = FALSE; } } $dbi->disconnect(); return $this->status; } function getUID() { return $this->user_id; } } ?> The following are the functions in this class: ◆ Authentication(): This is the constructor method, which sets the default values of the authentication object. First it sets the status variable to FALSE to signify that authentication is not successful yet. The e-mail vari- able is set to the e-mail address supplied as part of the parameter. (The authentication system uses e-mail address as the username and, therefore, it is a required item in the user-supplied credential.) The password para- meter is stored in the password variable. The function also sets the auth_tbl and db_url variables to authentica- tion table name and the fully qualified database name of the central authentication database. ◆ authenticate(): This function performs the authentication. It retrieves active UID and PASSWORD fields for the given e-mail address. If the user account has been deactivated (ACTIVE = 0), then the method returns default authentication status (FALSE), and if the user account is active and the encrypted version of the given password matches the stored crypto- graphic password, then the method returns TRUE status, which indicates successful authentication. 126 Part II: Developing Intranet Solutions 08 549669 ch05.qxd 4/4/03 9:24 AM Page 126 Now using this class (class.Authentication.php) and our existing application framework, let’s create central login and logout applications. Creating the Central Login Application The purpose of the login application is to present a username and password entry interface using an HTML template, and then to authenticate the user. If the user is successfully authenticated by the class.Authentication.php object, the login application creates the session data necessary to let other applica- tions know that the user is already authenticated and has valid credentials. If the user doesn’t supply valid credentials, the login application should allow the user to try a few times (say three times) and, if she fails after retrying for a config- urable number of times, then she is taken to an HTML page showing a warning about potential abuse of the system. This is to stop non-users from abusing the system. Valid users who have forgotten their passwords can run another login helper application to send new passwords via e-mail.This helper application is discussed in Chapter 6. Listing 5-2 shows the login application login.php, which implements these features. Listing 5-2: login.php <?php require_once “login.conf”; require_once “login.errors”; /* Session variables must be defined before session_start() method is called */ $count = 0; class loginApp extends PHPApplication { Continued Chapter 5: Central Authentication System 127 08 549669 ch05.qxd 4/4/03 9:24 AM Page 127 Listing 5-2 (Continued) function run() { global $MIN_USERNAME_SIZE, $MIN_PASSWORD_SIZE, $MAX_ATTEMPTS; global $WARNING_URL, $APP_MENU; $email = $this->getRequestField(‘email’); $password = $this->getRequestField(‘password’) ; $url = $this->getRequestField(‘url’); $emailLen = strlen($email); $passwdLen = strlen($password); $this->debug(“Login attempts : “ . $this- >getSessionField(‘SESSION_ATTEMPTS’)); if ($this->is_authenticated()) { // return to caller HTTP_REFERRER $this->debug(“User already authenticated.”); $this->debug(“Redirecting to $url.”); $url = (isset($url)) ? $url : $this->getServer(); header(“Location: $url”); } else if (strlen($email) < $MIN_USERNAME_SIZE || strlen($password) < $MIN_PASSWORD_SIZE) { // display the login interface $this->debug(“Invalid Email or password.”); $this->display_login(); $_SESSION[“SESSION_ATTEMPTS”] = $this- >getSessionField(“SESSION_ATTEMPTS”) + 1; } else { // Prepare the email with domain name if (!strpos($email, ‘’)) { $hostname = explode(‘.’, $_SERVER[‘SERVER_NAME’]); if (sizeof($hostname) > 1) { $email .= ‘’ . $hostname[1] . ‘.’ . $hostname[2]; } } 128 Part II: Developing Intranet Solutions 08 549669 ch05.qxd 4/4/03 9:24 AM Page 128 // authenticate user $this->debug(“Authenticate user: $email with password $password”); if ($this->authenticate($email, $password)) { $this->debug(“User is successfully authenticated.”); $_SESSION[“SESSION_USERNAME”] = $email; $_SESSION[“SESSION_PASSWORD”] = $password; $_SESSION[“SESSION_USER_ID”] = $this->getUID(); if (empty($url)) { $url = $APP_MENU; } // Log user activity $thisUser = new User($this->dbi, $this->getUID()); $thisUser->logActivity(LOGIN); $this->debug(“Location $url”); header(“Location: $url”); $this->debug(“Redirect user to caller application at url = $url.”); } else { $this->debug(“User failed authentication.”); $this->display_login(); $_SESSION[“SESSION_ATTEMPTS”] = $this- >getSessionField(“SESSION_ATTEMPTS”) + 1; } } } function warn() { global $WARNING_URL; $this->debug(“Came to warn the user $WARNING_URL”); header(“Location: $WARNING_URL”); } function display_login() { Continued Chapter 5: Central Authentication System 129 08 549669 ch05.qxd 4/4/03 9:24 AM Page 129 Listing 5-2 (Continued) global $TEMPLATE_DIR; global $LOGIN_TEMPLATE; global $MAX_ATTEMPTS; global $REL_TEMPLATE_DIR; global $email, $url; global $PHP_SELF, $FORGOTTEN_PASSWORD_APP; $url = $this->getRequestField(‘url’); if ($this->getSessionField(“SESSION_ATTEMPTS”) > $MAX_ATTEMPTS) { $this->warn(); } $this->debug(“Display login dialog box”); $template = new Template($TEMPLATE_DIR); $template->set_file(‘fh’, $LOGIN_TEMPLATE); $template->set_block(‘fh’, “mainBlock”); $template->set_var(‘SELF_PATH’, $PHP_SELF); $template->set_var(‘ATTEMPT’, $this- >getSessionField(“SESSION_ATTEMPTS”)); $template->set_var(‘TODAY’, date(“M-d-Y h:i:s a”)); $template->set_var(‘TODAY_TS’, time()); $template->set_var(‘USERNAME’, $email); $template->set_var(‘REDIRECT_URL’, $url); $template->set_var(‘FORGOTTEN_PASSWORD_APP’, $FORGOTTEN_PASSWORD_APP); $template->parse(“fh”, “mainBlock”); $template->set_var(‘BASE_URL’, sprintf(“%s”,$this->base_url)); $template->pparse(“output”, “fh”); return 1; } function is_authenticated() { return (!empty($_SESSION[“SESSION_USERNAME”])) ? TRUE : FALSE; } function authenticate($user = null, $passwd = null) { $authObj = new Authentication($user, $passwd, $this->app_db_url); 130 Part II: Developing Intranet Solutions 08 549669 ch05.qxd 4/4/03 9:24 AM Page 130 . discussed in Chapter 6. Listing 5-2 shows the login application login .php, which implements these features. Listing 5-2: login .php < ?php require_once “login.conf”; require_once “login.errors”; /* Session. to authenticate the user. If the user is successfully authenticated by the class.Authentication .php object, the login application creates the session data necessary to let other applica- tions. for a config- urable number of times, then she is taken to an HTML page showing a warning about potential abuse of the system. This is to stop non-users from abusing the system. Valid users who