Build a better Login with Adobe Flex, Zend_Amf, Zend_Auth, and Zend_Acl – On The PHP Side

December 26th, 2008

This is the server setup procedures for my tutorial Build a better Login with Flex, Zend_Amf, Zend_Auth, and Zend_Acl – On The Flex Side. Consult the first part of this tutorial for project requirements.

We previously created a folder under the MAMP installation called frameworks to serve as the home for the Zend library. Now we need to create a new folder to be the home for our applications server code.

Create a folder in the MAMP/htdocs dir named AccessControlExample.

Create a new folder in AccessControlExample dir and name it phplib, phplib will be the home of our applications main files.

In our main AccessControlExample dir, create a new file called index.php, this is known as the bootstrap file, if you need further clarification about the bootstrap file or any of the Zend Framework, please consult the Zend Framework Reference Guide.

Replace the contents of index.php with the following

<?php
// Error Reporting
error_reporting(E_ALL|E_STRICT);

// Turn to off when released to production
ini_set(”display_errors”,”on”);

// Modify include_path to include the
Zend library and the utils dir
ini_set(”include_path”, ini_get(”include_path”)
.PATH_SEPARATOR.”../../frameworks/”.
PATH_SEPARATOR.”../../utils/”);

// Zend Framework Includes
require_once ‘Zend/Loader.php’;
Zend_Loader::registerAutoload();

require_once ‘Zend/Amf/Server.php’;

require_once ‘ConnectionHelper.php’;
require_once ‘phplib/LoginVO.php’;
require_once ‘phplib/LoginManager.php’;

$server = new Zend_Amf_Server();
$server->setClass(’LoginManager’);
$server->setClass(”LoginVO”);

// Change this to true when released to production
$server->setProduction(false);

//Mapping the ActionScript VO to the PHP VO
//you don’t have to add the package name
$server->setClassMap(”LoginVO”,”LoginVO”);

echo($server->handle());

Basically this file provides a path to the Zend framework and any custom libraries we build that our application will need to function. We also map our PHP value Objects with our Actionscript value Objects here as well. Transferring data as Objects is much more efficient than making multiple calls for every piece of data.

Create a new PHP class inside the MAMP/utils dir named ConnectionHelper.php with the following code

<?php
class ConnectionHelper
{
public function __construct() {

$this->host=’localhost’;
$this->dbname=’AccessControlExample’;
$this->username =’root’;
$this->password = ‘root’;

}
}

Modify this file according to your particular needs.

Close ConnectionHelper.php.

Okay, we now need to create the 3 main php class files our application needs.

  1. LoginManager.php – this is the brains of the server side code. This is where we pass our users credentials to in order to authenticate and authorize the user to use our application. Remember Authenticate (Zend_Auth) and Authorize (Zend_Acl) are two different things.
  2. LoginVO.php – this is a value object, a very simple structure that describes our users login attributes.
  3. AccessPrivsVO.php – this is a value object, a very simple structure that describes our users role privileges.

Inside LoginManager.php paste the following,

<?php

require_once ‘ConnectionHelper.php’;
require_once ‘LoginVO.php’;
require_once ‘AccessPrivsVO.php’;
require_once ‘Zend/Auth.php’;
require_once ‘Zend/Acl.php’;

/*
* LoginManager
*
* Verify’s the users login credentials and
checks the users role against the ACL for access rights.
*
* @return Access Privileges
*/
class LoginManager {

private $dbAdapter;
private $authAdapter;

/**
* @return mixed
*/
public function __construct() {

// Get a reference to the
singleton instance of Zend_Auth
$this->auth = Zend_Auth::getInstance();

// Create database connection
try {
$conn = new ConnectionHelper();
$this->dbAdapter =
Zend_Db::factory(’Mysqli’,array(’host’ => $conn->host,
‘dbname’ => $conn->dbname,
‘username’ => $conn->username,
‘password’ => $conn->password));
}
catch ( Zend_Db_Exception $e){
return “Caught exception: ” . get_class($e) .
“\n Message: ” . $e->getMessage() . “\n”;
}
}

// test

/**
* @return void
*/
public function test() {
return “Success! Test Completed Normally”;
}

/**
*
* Authenticates the user
*
* @todo add routine to verify using SSO
*
* @return mixed
*
*/
public function verifyUser(LoginVO $user) {

$userRole=”;
// Configure the instance
with constructor parameters…
$authAdapter = new Zend_Auth_Adapter_DbTable(
$this->dbAdapter,
‘admin’,
‘username’,
‘password’);

$usr=htmlspecialchars($user->username);
$pwd=htmlspecialchars($user->password);
if($usr == ”){
$authAdapter
->setIdentity(’guest’)
->setCredential(’guest’);
}else{
$authAdapter
->setIdentity($usr)
->setCredential($pwd);
}
$result = $authAdapter->authenticate();

switch ($result->getCode()) {

case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$userRole = “guest”;
break;

case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$userRole = “guest”;
return “FAILURE_CREDENTIAL_INVALID”;
break;

case Zend_Auth_Result::FAILURE:
$userRole = ‘guest’;
break;

case Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS:
$userRole = ‘guest’;
break;

case Zend_Auth_Result::FAILURE_UNCATEGORIZED:
$userRole = ‘guest’;
break;

case Zend_Auth_Result::SUCCESS:

$this->sessionid=$this->getSessionID(); //revised 2/22/2009
// We need to return the authenticated
users role, this will be passed into the Zend_Acl
// getResultRowObject returns a stdClass
object so we need to dereference the role in this manner.
$r=$authAdapter->getResultRowObject(array(’role’));
$userRole = $r->role;
break;

default:
return “Internal Error! If this problem persist,
please contact your network administrator”;
break;
}

// Set up the ACL (Access Control List)
$acl = new Zend_Acl();
// Add groups to the Role registry using Zend_Acl_Role
// Guest does not inherit access controls.
// Order matters here, we go from the most
restricted to the least restricted
$acl->addRole(new Zend_Acl_Role(’guest’));
$acl->addRole(new Zend_Acl_Role(’manager’), ‘guest’);
$acl->addRole(new Zend_Acl_Role(’admin’), ‘manager’);

// Administrator does not inherit access controls,
All access is granted
$acl->addRole(new Zend_Acl_Role(’Super’));

// setup the resource privs
$acl->add(new Zend_Acl_Resource(’viewPublicUI’));
$acl->add(new Zend_Acl_Resource(’viewRestrictedUI’));
$acl->add(new Zend_Acl_Resource(’viewLogs’));
$acl->add(new Zend_Acl_Resource(’createManager’));

// Guest may only view the public interface
$acl->allow(’guest’, null, ‘viewPublicUI’);

// manager inherits viewPublicUI privilege from guest,
but also needs additional
// privileges
$acl->allow(’manager’, null, array(’viewRestrictedUI’));

// admin inherits viewRestrictedUI privilege from
// manager, but also needs additional privileges
$acl->allow(’admin’, null, array(’createManager’));

// Super inherits nothing, but is allowed all privileges
$acl->allow(’Super’);

// userRoleVO to Privs Map
$userRolePrivs = new AccessPrivsVO();
$userRolePrivs->userRole = $userRole;
$userRolePrivs->viewPublicUI =
$acl->isAllowed($userRole, null, ‘viewPublicUI’) ?
“allowed” : “denied”;
$userRolePrivs->viewRestrictedUI =
$acl->isAllowed($userRole, null, ‘viewRestrictedUI’) ?
“allowed” : “denied”;
$userRolePrivs->createManager =
$acl->isAllowed($userRole, null, ‘createManager’) ?
“allowed” : “denied”;
$userRolePrivs->viewLogs =
$acl->isAllowed($userRole, null, ‘viewLogs’) ?
“allowed” : “denied”;

return $userRolePrivs;

}
}

Inside LoginVO.php paste the following,

<?php
class LoginVO
{
//public $_explicitType = ‘LoginVO’;
public $userName=”;
public $password=”;
}

The variable $_explicitType is another way you could map the Actionscript VO to the PHP VO.

Inside AccessPrivsVO.php paste the following,

<?php
class AccessPrivsVO
{
public $userRole=”;
public $viewPublicUI=”;
public $createManager = ”;
public $viewRestrictedUI = ”;
public $viewLogs = ”;

}

You may have noticed I purposely left off the php closing tag ?>, this is to avoid troublesome errors caused by extra white space.

That’s it. You now have a robust login system that can be modified to meet your needs using Flex, PHP, Zend_Auth and Zend_Acl. Enjoy!

Categories: Flex, PHP, Zend

Tags: , , Leave a comment

Comments Feed7 Comments

  1. kevin

    Hi Craig,

    It’s been a little while since I’ve had time to test this login beauty out and I’ve struck an error I can’t seem to get around..

    When running the app and upon successful login with any valid creds, I get the PHP error:
    PHP Fatal error: Call to undefined method LoginManager::getSessionID()

    This seems to be relating to the line you’ve highlighted red in the above post.

    My code is:
    case Zend_Auth_Result::SUCCESS:$this->sessionid = $this->getSessionID();

    And running Zend v1.7.2

    Any ideas?

    cheers

  2. Keith

    Kevin,
    Hmm, not quite sure. Here’s a few things to try,
    I apologize if you’ve already already done this but without seeing your actual implementation this is off the top of my head.
    1. Make sure that the getSessionID() function is actually implemented.
    2. Did you intend on using sessionid as an instance variable, $this->sessionid instead as in my example a property of an object
    $userRolePrivs->sessionID ? This shouldn’t matter unless for some reason the instance is not being instantiated.
    3. You may want to upgrade the Zend library, the current version of the framework is 1.7.6.

  3. kevin

    Aha.. I thought getSessionID() was part of the Zend core.

    I used Wade’s article here to implement it and it now works:
    http://wadearnold.com/blog/?p=182

    cheers

  4. links for 2009-04-07 « Minesa IT

    [...] Build a better Login with Adobe Flex, Zend_Amf, Zend_Auth, and Zend_Acl – On The PHP Side – KeithCra… (tags: tutorials flash php framework flex zend zend_amf remoting zend_acl) [...]

  5. wow gold

    Well, to soon to say if it’s good, but at least it’s well designed.
    I mean I thought I would be blocked after adding some interests, but the site helps you to add more.
    Cheers

  6. terry

    Thanks! This was extraordinarily helpful. If you’ve downloaded the new Flash Builder 4 Beta, time for someone to refresh this whole thing using the new built-in structures for data connectivity… sigh… one more thing to re-learn.

  7. Keith

    Hi Terry,
    I’m glad you found this useful. I just downloaded the new Flash Builder beta. And I’m trying to come up to speed on the new Zend Framework architecture so hopefully I can make some time to upgrade the tutorials soon.
    Thank you

    Keith

Leave a comment

Feed

http://www.keithcraigo.com / Build a better Login with Adobe Flex, Zend_Amf, Zend_Auth, and Zend_Acl – On The PHP Side