IBM i developers often mistake Web designers as the enemy.
In the previous article, we went over how to use some Zend Framework classes in an actual procedural PHP script. We created a simple login/authentication script that could easily be combined with a login form to create a simple Web page/portal authentication system. So adding the login form is exactly what we are going to do in this article.
However, because IBM i developers often mistake Web designers as the enemy, we are also going to plug our PHP authentication script into a ready-made Web page. Note that the HTML, CSS, JavaScript, .jpgs, .pngs, and .gifs were all created by one of those brilliant, artistic Web designers. At the very least, it should be obvious that I didn't create them!
The only new Zend Framework class we are going to introduce is the Zend_View class. The Zend_View class exists specifically to keep your "view" scripts separate ("view" as in the "V" in MVC). I am not here to pitch the merits of the MVC design pattern. Remember: I promised to keep this article focused on using Zend Framework in the procedural programming model. But the more you understand about MVC, the easier it will be for you to develop full-blown MVC Zend Framework applications later on.
Changes to the Original Authorization Script
In order to make our original script capable of interacting directly with a login page, we'll need to make a few changes. First, we are going to encase the whole code block that does the actual authentication in an IF block, as shown below:
// ----------------------------------------------------------------------------
// if the form was POSTed. e.g. the user pressed the submit button.
// ----------------------------------------------------------------------------
if($_POST) {
//----------------------------------------------------------------------
// Set up the DB options
//----------------------------------------------------------------------
$library = 'jeffo';
// single database library option
$driverOptions = array( "i5_lib" => $library);
// Library list option
/* $driverOptions = array( "i5_naming" => DB2_I5_NAMING_ON,
"i5_libl" => "TBSCOMMON JMOQA2 JMOQA1 JMOPROD QGPL"); */
$config = array( "host" => "localhost",
"username" => "quser",
"password" => "quser",
"dbname" => "LEGATO3",
"driver_options" => $driverOptions);
if (!$db = Zend_Db::factory('DB2', $config)) {
echo "didn't create the DB adapter<br>";
die();
}
//-----------------------------------------------------------------------
// Setup the authentication database adapter
//-----------------------------------------------------------------------
if (!$authAdapter = new Zend_Auth_Adapter_DbTable($db)) {
echo "didn't create the Zend Auth Adapter table object<br>";
die();
}
// set the table and columns to use for authentication
$authAdapter
->setTableName('USERMSTR')
->setIdentityColumn('USER_PROFILE')
->setCredentialColumn('PASSWORD')
;
// Authenticate user
$authAdapter
->setIdentity(strip_tags($_POST['username']))
->setCredential(strip_tags($_POST['password']))
;
// authenticate using the specified credentials (specified above)
$authResult = $authAdapter->authenticate();
// display authentication results
switch ($authResult->getCode()) {
case Zend_Auth_Result::SUCCESS:
session_start();
$_SESSION['auth'] = true;
$_SESSION['authinfo'] = serialize($authAdapter->getResultRowObject());
header('location: memberhome.php');
break;
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$view->errorMessage = "User Identity not found. Login unsuccessful";
$view->errorFnd = true;
break;
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$view->errorMessage = "User/Password combination not valid. Login unsuccessful";
$view->errorFnd = true;
break;
default:
$view->errorMessage = "Login unsuccessful. Unidentified error";
$view->errorFnd = true;
}
}
The IF block is comparing to see if the $_POST superglobal variable has a "true" value (anything other than zero or null). This will be true only when the script has received "post" input from a form—meaning once the user has entered data in the form and pressed the login button. If we do not have the post data, then we are simply going to display the "home page" and the login (see testauth.php in the zip file).
The other thing we have to do to the testauth.php script is add the handling of the view/form. So we are going to create a Zend_View object and display the home page and login form. This will also require some changes to the authentication processing. See code changes below:
<?php
//-------------------------------------------------------------------------------
// Set to display errors - TESTING ONLY!!
//-------------------------------------------------------------------------------
ini_set('display_errors', '1');
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
//-------------------------------------------------------------------------------
// Use Autoloader to include the Zend Framework Classes we are going to use.
//-------------------------------------------------------------------------------
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
$view = new zend_view();
$view->setScriptPath(realpath(dirname(__FILE__)));
// ------------------------------------------------------------------------------
// if the form was POSTed; e.g., the user pressed the submit button.
// ------------------------------------------------------------------------------
if($_POST) {
//----------------------------------------------------------------------------
// Set up the DB options
//---------------------------------------------------------------------------
$library = 'jeffo';
// single database library option
$driverOptions = array( "i5_lib" => $library);
// Library list option
/* $driverOptions = array( "i5_naming" => DB2_I5_NAMING_ON,
"i5_libl" => "TBSCOMMON JMOQA2 JMOQA1 JMOPROD QGPL"); */
$config = array( "host" => "localhost",
"username" => "quser",
"password" => "quser",
"dbname" => "LEGATO3",
"driver_options" => $driverOptions);
if (!$db = Zend_Db::factory('DB2', $config)) {
echo "didn't create the DB adapter<br>";
die();
}
//-----------------------------------------------------------------------------
// Set up the authentication database adapter
//-----------------------------------------------------------------------------
if (!$authAdapter = new Zend_Auth_Adapter_DbTable($db)) {
echo "didn't create the Zend Auth Adapter table object<br>";
die();
}
// set the table and columns to use for authentication
$authAdapter
->setTableName('USERMSTR')
->setIdentityColumn('USER_PROFILE')
->setCredentialColumn('PASSWORD')
;
// Authenticate user
$authAdapter
->setIdentity(strip_tags($_POST['username']))
->setCredential(strip_tags($_POST['password']))
;
// authenticate using the specified credentials (specified above)
$authResult = $authAdapter->authenticate();
// display authentication results
switch ($authResult->getCode()) {
case Zend_Auth_Result::SUCCESS:
session_start();
$_SESSION['auth'] = true;
$_SESSION['authinfo'] = serialize($authAdapter->getResultRowObject());
header('location: memberhome.php');
break;
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$view->errorMessage = "User Identity not found. Login unsuccessful";
$view->errorFnd = true;
break;
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$view->errorMessage = "User/Password combination not valid. Login unsuccessful";
$view->errorFnd = true;
break;
default:
$view->errorMessage = "Login unsuccessful. Unidentified error";
$view->errorFnd = true;
}
}
echo $view->render('home.php');
?>
Let's look at each change in detail. First, we are creating an instance of the Zend_View object. Then we are setting the script path, the path that will be searched to find your "view" scripts when you reference them. We set the path using the setScriptPath method of the Zend_View object. In this case, our view script is always in the same subdirectory as the current file. So that's what we set the script path to.
$view = new zend_view();
$view->setScriptPath(realpath(dirname(__FILE__)));
The next changed code block is the actual authentication code. All we are doing here is changing the authentication to use the values passed from the form (from the $_POST variable). Notice that we are doing a bit of data sanitizing by using the strip_tags function. This is a good habit to get into. Realistically, you should treat all your input data as potentially hostile.
// Authenticate user
$authAdapter
->setIdentity(strip_tags($_POST['username']))
->setCredential(strip_tags($_POST['password']))
;
Then we change the results when the user is authenticated successfully. The new process will start a session so that we can keep some data values between scripts. That will be necessary later, when we need to know if a user has been authenticated or not. Also, when a user is authenticated successfully, we will re-direct the user to a "logged in" page.
In the event of an unsuccessful authentication, we are going to create an error flag and error message for our view. That completes the authentication processing. At this point, if the user wasn't authenticated successfully or if there was no $_POST data, we will display the login page (or re-display it in the case of an unsuccessful authentication).
case Zend_Auth_Result::SUCCESS:
session_start();
$_SESSION['auth'] = true;
$_SESSION['authinfo'] = serialize($authAdapter->getResultRowObject());
header('location: memberhome.php');
break;
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$view->errorMessage = "User Identity not found. Login unsuccessful";
$view->errorFnd = true;
break;
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$view->errorMessage = "User/Password combination not valid. Login unsuccessful";
$view->errorFnd = true;
break;
default:
$view->errorMessage = "Login unsuccessful. Unidentified error";
$view->errorFnd = true;
}
}
echo $view->render('home.php');
Note that we can create properties for our view; we'll simply be giving them values (as in $view->errorFnd and $view->errorMessage).
To actually display our view script, we use the render method of the Zend_View object to "render" the contents of the script specified ("home.php" in this case) into HTML. Then we use the ECHO construct to output that HTML to the display.
The "Home" Page View
The actual "home.php" view script is one of those amazing HTML pages created by a Web designer…with a few little additions we need for our login. The whole script is too long to display here, so I am going to show only the code changes we are making to the original code.
<div>
<div>
<h2>Welcome to Our Motor Club!</h2>
<p>Motor is a free websites template created by Templates.com team. This website template is optimized for 1024X768 screen resolution. It is also XHTML & CSS valid.</p>
<p>The website template goes with two packages—with PSD source files and without them. PSD source files are available for free for the registered members of Templates.com. The basic package (without PSD is available for anyone without registration).</p>
<p>This website template has several pages: Home, About us, Article (with Article page), Contact us (note that contact us form doesn't work), Site Map.</p>
</div>
</div>
<div>
<div>
<h2>Login</h2>
<form method="post" action="testauth.php">
<table ><tr>
<?php
if ($this->errorFnd) {
echo "<td colspan=2><font color=red>".$this->errorMessage."</font><br/></td> </tr><tr>";
}
?>
<td align="right">Username:</td>
<td align="left"><input length=20 value="
"></input></td></tr>
<tr><td align="right">Password:</td>
<td align="left"><input length=20></td></tr>
<tr><td colspan=2 align="center"><input value="Login"></td></tr>
</table>
</form>
</div>
</div>
<div>
<div>
<div>
So all we have to do to the nice page that was already designed by someone else is add our login form and the processing to go with it. In this case, that means setting our form action to our authentication script "testauth.php". It also means checking the value of our properties we set in the "testauth.php" script. So if the errorFnd property is set to TRUE, then we know that an error in authentication took place and we need to display the errorMessage ($this->errorFnd and $this->errorMessage now because we are actually within the view page now).
So What?!
So this is all well and good, but really…so what? Well, I'm going to show you what. The last page we are going to modify is the "memberhome.php" page. This page will be a (somewhat) secure page that will be accessible only to members who have logged in. This is how we will accomplish that:
<?php
session_start();
if(!$_SESSION['auth']) {
header("Location: testauth.php");
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Home - Home Page | Motor - Free Website Template from Templates.com</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta content="Place your description here" />
At the very top of the "memberhome.php" script, we add code that starts a session that will give us access to those "saved" values we placed in the $_SESSION superglobal variable when the user was authenticated. If the "auth" value is true, the user has been authenticated and the Web page will be displayed. Otherwise, the user will be redirected back to "testauth.php" to be authenticated.
New Class, New Friends
I hope this gives you some good insight into how to create some basic authentication for your Web sites and also how to use the Zend_View class. In addition, maybe you'll decide to befriend your company's Web designer so you can get him/her to do the heavy lifting for you.
as/400, os/400, iseries, system i, i5/os, ibm i, power systems, 6.1, 7.1, V7,
LATEST COMMENTS
MC Press Online