Ver código fonte

merge Auth support and resources support from incubator
fixes ZF-6202 and ZF-6230


git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@15896 44c647ce-9c0f-0410-b52a-842ac1e357ba

stas 16 anos atrás
pai
commit
480aefd5d6

+ 132 - 0
library/Zend/Amf/Adobe/Auth.php

@@ -0,0 +1,132 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Amf
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Amf_Auth_Abstract */
+require_once 'Zend/Amf/Auth/Abstract.php';
+
+/** Zend_Acl */
+require_once 'Zend/Acl.php';
+
+/** Zend_Auth_Result */
+require_once 'Zend/Auth/Result.php';
+
+/**
+ * This class implements authentication against XML file with roles for Flex Builder.
+ *
+ * @package    Zend_Amf
+ * @subpackage Adobe
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Amf_Adobe_Auth extends Zend_Amf_Auth_Abstract
+{
+    
+    /**
+     * ACL for authorization
+     * 
+     * @var Zend_Acl
+     */
+    protected $_acl;
+    
+    /**
+     * Username/password array
+     * 
+     * @var array
+     */
+    protected $_users = array();
+    
+    /**
+     * Create auth adapter
+     * 
+     * @param string $rolefile File containing XML with users and roles
+     */
+    public function __construct($rolefile)
+    {
+        $this->_acl = new Zend_Acl();
+        $xml = simplexml_load_file($rolefile);
+/*
+Roles file format:
+ <roles>
+   <role id=”admin”>
+        <user name=”user1” password=”pwd”/>
+    </role>
+   <role id=”hr”>
+        <user name=”user2” password=”pwd2”/>
+    </role>    
+</roles>
+*/
+        foreach($xml->role as $role) {
+            $this->_acl->addRole(new Zend_Acl_Role((string)$role["id"]));
+            foreach($role->user as $user) {
+		        $this->_users[(string)$user["name"]] = array("password" => (string)$user["password"], 
+		        										"role" => (string)$role["id"]);
+	        }
+        }
+    }
+    
+    /**
+     * Get ACL with roles from XML file
+     * 
+     * @return Zend_Acl
+     */
+    public function getAcl()
+    {
+        return $this->_acl;
+    }
+    
+    /**
+     * Perform authentication
+     * 
+     * @throws Zend_Auth_Adapter_Exception
+     * @return Zend_Auth_Result
+     * @see Zend_Auth_Adapter_Interface#authenticate()
+     */
+    public function authenticate()
+    {
+        if (empty($this->_username) ||
+            empty($this->_password)) {
+            /**
+             * @see Zend_Auth_Adapter_Exception
+             */
+            require_once 'Zend/Auth/Adapter/Exception.php';
+            throw new Zend_Auth_Adapter_Exception('Username/password should be set');
+        }
+        
+        if(!isset($this->_users[$this->_username])) {
+            return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND,
+                null,
+                array('Username not found')
+                );
+        }
+        
+        $user = $this->_users[$this->_username];
+        if($user["password"] != $this->_password) {
+            return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID,
+                null,
+                array('Authentication failed')
+                );
+        }
+        
+        $id = new stdClass();
+        $id->role = $user["role"];
+        $id->name = $this->_username;
+        return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $id);
+    }
+}

+ 102 - 0
library/Zend/Amf/Adobe/DbInspector.php

@@ -0,0 +1,102 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Amf
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * This class implements authentication against XML file with roles for Flex Builder.
+ *
+ * @package    Zend_Amf
+ * @subpackage Adobe
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Amf_Adobe_DbInspector
+{
+
+	/**
+	 * Connect to the database
+	 *
+	 * @param string $dbType Database adapter type for Zend_Db
+	 * @param array|object $dbDescription Adapter-specific connection settings
+	 * @return Zend_Db_Adapter_Abstract
+	 * @see Zend_Db::factory()
+	 */
+	protected function _connect($dbType, $dbDescription) 
+	{
+		if(is_object($dbDescription)) {
+			$dbDescription = get_object_vars($dbDescription);
+		}
+		return Zend_Db::factory($dbType, $dbDescription);
+	}
+	
+	/**
+	 * Describe database object. 
+	 * 
+	 * Usage example:
+	 * $inspector->describeTable('Pdo_Mysql', 
+	 * 		array(
+	 * 			'host'     => '127.0.0.1',
+	 *			'username' => 'webuser',
+	 *			'password' => 'xxxxxxxx',
+	 *			'dbname'   => 'test'
+	 * 		),
+	 * 		'mytable'
+	 * 	);
+	 *
+	 * @param string $dbType Database adapter type for Zend_Db
+	 * @param array|object $dbDescription Adapter-specific connection settings
+	 * @param string $tableName Table name
+	 * @return array Table description
+	 * @see Zend_Db::describeTable()
+	 * @see Zend_Db::factory()
+	 */
+	public function describeTable($dbType, $dbDescription, $tableName) 
+	{
+		$db = $this->_connect($dbType, $dbDescription);
+		return $db->describeTable($tableName);
+	}
+
+	/**
+	 * Test database connection
+	 *
+	 * @param string $dbType Database adapter type for Zend_Db
+	 * @param array|object $dbDescription Adapter-specific connection settings
+	 * @return bool
+	 * @see Zend_Db::factory()
+	 */
+	public function connect($dbType, $dbDescription) 
+	{
+		$db = $this->_connect($dbType, $dbDescription);
+		$db->listTables();
+		return true;
+	}
+	
+	/**
+	 * Get the list of database tables
+	 *
+	 * @param string $dbType Database adapter type for Zend_Db
+	 * @param array|object $dbDescription Adapter-specific connection settings
+	 * @return array List of the tables
+	 */
+	public function getTables($dbType, $dbDescription) 
+	{
+		$db = $this->_connect($dbType, $dbDescription);
+		return $db->listTables();
+	}
+}

+ 41 - 0
library/Zend/Amf/Auth/Abstract.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Amf
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Auth_Adapter_Interface */
+require_once 'Zend/Auth/Adapter/Interface.php';
+
+/**
+ * Base abstract class for AMF authentication implementation
+ *
+ * @package    Zend_Amf
+ * @subpackage Auth
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Amf_Auth_Abstract implements Zend_Auth_Adapter_Interface
+{
+    protected $_username;
+    protected $_password;
+    
+    public function setCredentials($username, $password) {
+		$this->_username = $username;
+		$this->_password = $password;
+	}
+}

+ 5 - 0
library/Zend/Amf/Constants.php

@@ -76,4 +76,9 @@ final class Zend_Amf_Constants
     const URL_APPEND_HEADER      = 'AppendToGatewayUrl';
     const RESULT_METHOD          = '/onResult';
     const STATUS_METHOD          = '/onStatus';
+    const CREDENTIALS_HEADER     = 'Credentials';
+    const PERSISTENT_HEADER      = 'RequestPersistentHeader';
+    const DESCRIBE_HEADER        = 'DescribeService';
+    
+    const GUEST_ROLE             = 'anonymous';
 }

+ 4 - 1
library/Zend/Amf/Parse/Amf0/Serializer.php

@@ -95,8 +95,11 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
                     throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
             }
         } else {
+            if(is_resource($data)) {
+                $data = Zend_Amf_Parse_TypeLoader::handleResource($data);
+            }
             switch (true) {
-                case (is_int($data) || is_float($data)):
+            	case (is_int($data) || is_float($data)):
                     $markerType = Zend_Amf_Constants::AMF0_NUMBER;
                     break;
                 case (is_bool($data)):

+ 3 - 1
library/Zend/Amf/Parse/Amf3/Deserializer.php

@@ -78,6 +78,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
         if(null === $typeMarker) {
             $typeMarker = $this->_stream->readByte();
         }
+
         switch($typeMarker) {
             case Zend_Amf_Constants::AMF3_UNDEFINED:
                  return null;
@@ -330,7 +331,6 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
             // Add the Object ot the reference table
             $this->_referenceObjects[] = $returnObject;
 
-            $properties = array();
             // Check encoding types for additional processing.
             switch ($encoding) {
                 case (Zend_Amf_Constants::ET_EXTERNAL):
@@ -354,6 +354,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
                         );
                     }
                     // not a refrence object read name value properties from byte stream
+                    $properties = array(); // clear value
                     do {
                         $property = $this->readString();
                         if ($property != "") {
@@ -376,6 +377,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
                             'propertyNames' => $propertyNames,
                         );
                     }
+                    $properties = array(); // clear value
                     foreach ($propertyNames as $property) {
                         $properties[$property] = $this->readTypeMarker();
                     }

+ 4 - 1
library/Zend/Amf/Parse/Amf3/Serializer.php

@@ -89,8 +89,11 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
             }
         } else {
             // Detect Type Marker
+            if(is_resource($data)) {
+                $data = Zend_Amf_Parse_TypeLoader::handleResource($data);
+            }
              switch (true) {
-                case (null === $data):
+             	case (null === $data):
                     $markerType = Zend_Amf_Constants::AMF3_NULL;
                     break;
                 case (is_bool($data)):

+ 69 - 0
library/Zend/Amf/Parse/Resource/MysqlResult.php

@@ -0,0 +1,69 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Amf
+ * @subpackage Parse
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * This class will convert mysql result resource to array suitable for passing 
+ * to the external entities.
+ *
+ * @package    Zend_Amf
+ * @subpackage Parse
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Amf_Parse_Resource_MysqlResult 
+{
+    /**
+     * @var array List of Mysql types with PHP counterparts
+     * 
+     * Key => Value is Mysql type (exact string) => PHP type
+     */
+    static public $fieldTypes = array(
+        "int" => "int",
+        "timestamp" => "int",
+        "year" => "int",
+    	"real" => "float",
+    );
+    /**
+     * Parse resource into array
+     * 
+     * @param resource $resource
+     * @return array
+     */
+    public function parse($resource) {
+        $result = array();
+        $fieldcnt = mysql_num_fields($resource);
+        $fields_transform = array();
+        for($i=0;$i<$fieldcnt;$i++) {
+            $type = mysql_field_type($resource, $i);
+            if(isset(self::$fieldTypes[$type])) {
+                $fields_transform[mysql_field_name($resource, $i)] = self::$fieldTypes[$type];
+            }
+        }
+
+        while($row = mysql_fetch_assoc($resource)) {
+            foreach($fields_transform as $fieldname => $fieldtype) {
+               settype($row[$fieldname], $fieldtype);
+            }
+            $result[] = $row;
+        }
+        return $result;
+    }
+}

+ 41 - 0
library/Zend/Amf/Parse/Resource/Stream.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Amf
+ * @subpackage Parse
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * This class will convert stream resource to string by just reading it
+ *
+ * @package    Zend_Amf
+ * @subpackage Parse
+ * @copyright  Copyright (c) 2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Amf_Parse_Resource_Stream
+{
+    /**
+     * Parse resource into string
+     * 
+     * @param resource $resource Stream resource
+     * @return array
+     */
+    public function parse($resource) {
+        return stream_get_contents($resource);
+    }
+}

+ 81 - 0
library/Zend/Amf/Parse/TypeLoader.php

@@ -64,6 +64,12 @@ final class Zend_Amf_Parse_TypeLoader
         'flex.messaging.messages.RemotingMessage'    => 'Zend_Amf_Value_Messaging_RemotingMessage',
         'flex.messaging.io.ArrayCollection'          => 'Zend_Amf_Value_Messaging_ArrayCollection',
     );
+    
+    /**
+     * @var Zend_Loader_PluginLoader_Interface
+     */
+    protected static $_resourceLoader = null;
+
 
     /**
      * Load the mapped class type into a callback.
@@ -131,4 +137,79 @@ final class Zend_Amf_Parse_TypeLoader
     {
         self::$classMap = self::$_defaultClassMap;
     }
+    
+    /**
+     * Set loader for resource type handlers
+     * 
+     * @param Zend_Loader_PluginLoader_Interface $loader  
+     */
+    public static function setResourceLoader(Zend_Loader_PluginLoader_Interface $loader)
+    {
+    	self::$_resourceLoader = $loader;
+    }
+    
+    /**
+	 * Add directory to the list of places where to look for resource handlers
+	 *
+     * @param string $prefix
+     * @param string $dir
+     */
+    public static function addResourceDirectory($prefix, $dir)
+    {
+    	if(self::$_resourceLoader) {
+    		self::$_resourceLoader->addPrefixPath($prefix, $dir);
+    	} 
+    }
+    
+    /**
+     * Get plugin class that handles this resource
+     * 
+     * @param resource $resource Resource type
+     * @return string Class name
+     */
+    public static function getResourceParser($resource)
+    {
+    	if(self::$_resourceLoader) {
+   			$type = preg_replace("/[^A-Za-z0-9_]/", " ", get_resource_type($resource));
+   			$type = str_replace(" ","", ucwords($type));
+   			return self::$_resourceLoader->load($type);
+    	}
+    	return false;
+    }
+    
+    /**
+     * Convert resource to a serializable object
+     * 
+     * @param resource $resource
+     * @return mixed
+     */
+    public static function handleResource($resource)
+    {
+		if(!self::$_resourceLoader) {
+			require_once 'Zend/Amf/Exception.php';
+			throw new Zend_Amf_Exception('Unable to handle resources - resource plugin loader not set');
+		}
+    	try {
+    		while(is_resource($resource)) {
+				$resclass = self::getResourceParser($resource);
+				if(!$resclass) {
+					require_once 'Zend/Amf/Exception.php';
+					throw new Zend_Amf_Exception('Can not serialize resource type: '. get_resource_type($resource));
+				}
+				$parser = new $resclass();
+				if(is_callable(array($parser, 'parse'))) {
+					$resource = $parser->parse($resource);
+				} else {
+					require_once 'Zend/Amf/Exception.php';
+					throw new Zend_Amf_Exception("Could not call parse() method on class $resclass");
+				}
+    		}
+			return $resource;	
+		} catch(Zend_Amf_Exception $e) {
+			throw $e;
+		} catch(Exception $e) {
+			require_once 'Zend/Amf/Exception.php';
+			throw new Zend_Amf_Exception('Can not serialize resource type: '. get_resource_type($resource));
+		}
+    }
 }

+ 240 - 32
library/Zend/Amf/Server.php

@@ -36,9 +36,14 @@ require_once 'Zend/Amf/Value/MessageHeader.php';
 /** Zend_Amf_Value_Messaging_CommandMessage */
 require_once 'Zend/Amf/Value/Messaging/CommandMessage.php';
 
+/** Zend_Loader_PluginLoader */
+require_once 'Zend/Loader/PluginLoader.php';
+
 /** Zend_Amf_Parse_TypeLoader */
 require_once 'Zend/Amf/Parse/TypeLoader.php';
 
+/** Zend_Auth */
+require_once 'Zend/Auth.php';
 /**
  * An AMF gateway server implementation to allow the connection of the Adobe Flash Player to
  * Zend Framework
@@ -100,11 +105,73 @@ class Zend_Amf_Server implements Zend_Server_Interface
 
     /**
      * Set the default session.name if php_
-     * @var unknown_type
+     * @var string
      */
     protected $_sessionName = 'PHPSESSID';
 
     /**
+     * Authentication handler object
+     * 
+     * @var Zend_Amf_Auth_Abstract
+     */
+    protected $_auth;
+    /**
+     * ACL handler object
+     * 
+     * @var Zend_Acl
+     */
+    protected $_acl;
+    /**
+     * The server constructor
+     */
+    public function __construct()
+    {
+    	Zend_Amf_Parse_TypeLoader::setResourceLoader(new Zend_Loader_PluginLoader(array("Zend_Amf_Parse_Resource" => "Zend/Amf/Parse/Resource")));
+    }
+    
+    /**
+     * Set authentication adapter
+     *
+     * @param  Zend_Amf_Auth_Abstract $auth
+     * @return Zend_Amf_Server
+     */
+    public function setAuth(Zend_Amf_Auth_Abstract $auth)
+    {
+        $this->_auth = $auth;
+        return $this;
+    }
+   /**
+     * Get authentication adapter
+     *
+     * @return Zend_Amf_Auth_Abstract
+     */
+    public function getAuth()
+    {
+        return $this->_auth;
+    }
+    
+    /**
+     * Set ACL adapter
+     *
+     * @param  Zend_Acl $acl
+     * @return Zend_Amf_Server
+     */
+    public function setAcl(Zend_Acl $acl)
+    {
+        $this->_acl = $acl;
+        return $this;
+    }
+   /**
+     * Get ACL adapter
+     *
+     * @return Zend_Acl
+     */
+    public function getAcl()
+    {
+        return $this->_acl;
+    }
+    
+    /**
      * Set production flag
      *
      * @param  bool $flag
@@ -148,6 +215,52 @@ class Zend_Amf_Server implements Zend_Server_Interface
     }
 
     /**
+     * Check if the ACL allows accessing the function or method 
+     * 
+     * @param string|object $object Object or class being accessed
+     * @param string $function Function or method being acessed
+     * @return unknown_type
+     */
+    protected function _checkAcl($object, $function)
+    {
+        if(!$this->_acl) {
+            return true;
+        }
+        if($object) {
+            $class = is_object($object)?get_class($object):$object;
+            if(!$this->_acl->has($class)) {
+            	require_once 'Zend/Acl/Resource.php';
+                $this->_acl->add(new Zend_Acl_Resource($class));
+            }
+            $call = array($object, "initAcl");
+            if(is_callable($call) && !call_user_func($call, $this->_acl)) {
+                // if initAcl returns false, no ACL check
+                return true;
+            }
+        } else {
+            $class = null;
+        }
+        
+        $auth = Zend_Auth::getInstance();
+        if($auth->hasIdentity()) {
+            $role = $auth->getIdentity()->role;
+        } else {
+        	if($this->_acl->hasRole(Zend_Amf_Constants::GUEST_ROLE)) {
+                $role = Zend_Amf_Constants::GUEST_ROLE;
+            } else {
+            	require_once 'Zend/Amf/Server/Exception.php';
+                throw new Zend_Amf_Server_Exception("Unauthenticated access not allowed");
+            }
+        }
+        if($this->_acl->isAllowed($role, $class, $function)) {
+            return true;
+        } else {
+            require_once 'Zend/Amf/Server/Exception.php';
+            throw new Zend_Amf_Server_Exception("Access not allowed");
+        }
+    }
+    
+    /**
      * Loads a remote class or method and executes the function and returns
      * the result
      *
@@ -178,14 +291,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
                     $classPath[] = $dir . $uriclasspath;
                 }
 
-                if (!class_exists($className)) {
-                    try {
-                        require_once 'Zend/Loader.php';
-                        Zend_Loader::loadClass($className, $classPath);
-                    } catch (Exception $e) {
-                        require_once 'Zend/Amf/Server/Exception.php';
-                        throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist');
-                    }
+                require_once('Zend/Loader.php');
+                try {
+                    Zend_Loader::loadClass($className, $classPath);
+                } catch (Exception $e) {
+                    require_once 'Zend/Amf/Server/Exception.php';
+                    throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist');
                 }
                 // Add the new loaded class to the server.
                 $this->setClass($className, $source);
@@ -204,6 +315,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
 
         if ($info instanceof Zend_Server_Reflection_Function) {
             $func = $info->getName();
+            $this->_checkAcl(null, $func);
             $return = call_user_func_array($func, $params);
         } elseif ($info instanceof Zend_Server_Reflection_Method) {
             // Get class
@@ -212,6 +324,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
                 // for some reason, invokeArgs() does not work the same as
                 // invoke(), and expects the first argument to be an object.
                 // So, using a callback if the method is static.
+                $this->_checkAcl($class, $info->getName());
                 $return = call_user_func_array(array($class, $info->getName()), $params);
             } else {
                 // Object methods
@@ -221,6 +334,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
                     require_once 'Zend/Amf/Server/Exception.php';
                     throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName(), 621);
                 }
+                $this->_checkAcl($object, $info->getName());
                 $return = $info->invokeArgs($object, $params);
             }
         } else {
@@ -242,9 +356,29 @@ class Zend_Amf_Server implements Zend_Server_Interface
      */
     protected function _loadCommandMessage(Zend_Amf_Value_Messaging_CommandMessage $message)
     {
+        require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
         switch($message->operation) {
             case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION :
-                require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
+                $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
+                break;
+            case Zend_Amf_Value_Messaging_CommandMessage::LOGIN_OPERATION :
+                $data = explode(':', base64_decode($message->body));
+            	$userid = $data[0];
+            	$password = isset($data[1])?$data[1]:""; 
+                if(empty($userid)) {
+                    require_once 'Zend/Amf/Server/Exception.php';
+                    throw new Zend_Amf_Server_Exception('Login failed: username not supplied');
+                }
+                if(!$this->_handleAuth($userid, $password)) {
+                    require_once 'Zend/Amf/Server/Exception.php';
+                    throw new Zend_Amf_Server_Exception('Authentication failed');
+                }
+                $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
+                break;
+           case Zend_Amf_Value_Messaging_CommandMessage::LOGOUT_OPERATION :
+                if($this->_auth) {
+                    Zend_Auth::getInstance()->clearIdentity();
+                }
                 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
                 break;
             default :
@@ -256,10 +390,73 @@ class Zend_Amf_Server implements Zend_Server_Interface
     }
 
     /**
+     * Create appropriate error message
+     * 
+     * @param int $objectEncoding Current AMF encoding
+     * @param string $message Message that was being processed when error happened
+     * @param string $description Error description
+     * @param mixed $detail Detailed data about the error
+     * @param int $code Error code
+     * @param int $line Error line
+     * @return Zend_Amf_Value_Messaging_ErrorMessage|array
+     */
+    protected function _errorMessage($objectEncoding, $message, $description, $detail, $code, $line)
+    {
+        $return = null;
+		switch ($objectEncoding) {
+			case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
+				return array (
+						'description' => ($this->isProduction ()) ? '' : $description, 
+						'detail' => ($this->isProduction ()) ? '' : $detail, 
+						'line' => ($this->isProduction ()) ? 0 : $line, 
+						'code' => $code 
+			    );
+			case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
+				require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
+				$return = new Zend_Amf_Value_Messaging_ErrorMessage ( $message );
+				$return->faultString = $this->isProduction () ? '' : $description;
+				$return->faultCode = $code;
+				$return->faultDetail = $this->isProduction () ? '' : $detail;
+				break;
+		}
+        return $return;
+    }
+
+	/**
+	 * Handle AMF authenticaton
+	 * 
+	 * @param string $userid
+	 * @param string $password
+	 * @return boolean
+	 */
+	protected function _handleAuth( $userid,  $password)
+	{
+		if (!$this->_auth) {
+			return true;
+		}
+		$this->_auth->setCredentials($userid, $password);
+		$auth = Zend_Auth::getInstance();
+		$result = $auth->authenticate($this->_auth);
+		if ($result->isValid()) {
+			if (!$this->isSession()) {
+				$this->setSession();
+			}
+			return true;
+		} else {
+			// authentication failed, good bye
+			require_once 'Zend/Amf/Server/Exception.php';
+			throw new Zend_Amf_Server_Exception(
+				"Authentication failed: " . join("\n", 
+					$result->getMessages()), $result->getCode());
+		}
+	        
+    }
+    
+    /**
      * Takes the deserialized AMF request and performs any operations.
      *
      * @todo   should implement and SPL observer pattern for custom AMF headers
-     * @todo   implement AMF header authentication
+     * @todo   DescribeService support
      * @param  Zend_Amf_Request $request
      * @return Zend_Amf_Response
      * @throws Zend_Amf_server_Exception|Exception
@@ -274,16 +471,42 @@ class Zend_Amf_Server implements Zend_Server_Interface
 
         // set reponse encoding
         $response->setObjectEncoding($objectEncoding);
-
+        
         $responseBody = $request->getAmfBodies();
 
+        $handleAuth = false;
+		if ($this->_auth) {
+			$headers = $request->getAmfHeaders();
+			if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) && 
+			    isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
+				$handleAuth = true;
+			}
+		}
+        
         // Iterate through each of the service calls in the AMF request
         foreach($responseBody as $body)
         {
-            try {
+            try {
+				if ($handleAuth) {
+					if ($this->_handleAuth(
+						$headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, 
+						$headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) {
+						// use RequestPersistentHeader to clear credentials                     
+						$response->addAmfHeader(
+							new Zend_Amf_Value_MessageHeader(
+								Zend_Amf_Constants::PERSISTENT_HEADER, 
+								false, 
+								new Zend_Amf_Value_MessageHeader(
+									Zend_Amf_Constants::CREDENTIALS_HEADER, 
+									false, null)));
+						$handleAuth = false;
+					}
+				}
+                
                 if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) {
                     // AMF0 Object Encoding
                     $targetURI = $body->getTargetURI();
+                    $message = '';
 
                     // Split the target string into its values.
                     $source = substr($targetURI, 0, strrpos($targetURI, '.'));
@@ -325,23 +548,8 @@ class Zend_Amf_Server implements Zend_Server_Interface
                 }
                 $responseType = Zend_AMF_Constants::RESULT_METHOD;
             } catch (Exception $e) {
-                switch ($objectEncoding) {
-                    case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
-                        $return = array(
-                            'description' => ($this->isProduction()) ? '' : $e->getMessage(),
-                            'detail'      => ($this->isProduction()) ? '' : $e->getTraceAsString(),
-                            'line'        => ($this->isProduction()) ? 0  : $e->getLine(),
-                            'code'        => $e->getCode(),
-                        );
-                        break;
-                    case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
-                        require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
-                        $return = new Zend_Amf_Value_Messaging_ErrorMessage($message);
-                        $return->faultString = $this->isProduction() ? '' : $e->getMessage();
-                        $return->faultCode   = $e->getCode();
-                        $return->faultDetail = $this->isProduction() ? '' : $e->getTraceAsString();
-                        break;
-                }
+                $return = $this->_errorMessage($objectEncoding, $message, 
+                    $e->getMessage(), $e->getTraceAsString(),$e->getCode(),  $e->getLine());
                 $responseType = Zend_AMF_Constants::STATUS_METHOD;
             }
 
@@ -363,7 +571,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
            
             // create a new AMF message header with the session id as a variable.
             $sessionValue = $joint . $this->_sessionName . "=" . $currentID;
-            $sessionHeader = new Zend_Amf_Value_MessageHeader("AppendToGatewayUrl", false, $sessionValue);
+            $sessionHeader = new Zend_Amf_Value_MessageHeader(Zend_Amf_Constants::URL_APPEND_HEADER, false, $sessionValue);
             $response->addAmfHeader($sessionHeader);
         }
 
@@ -701,4 +909,4 @@ class Zend_Amf_Server implements Zend_Server_Interface
     {
         return array_keys($this->_table);
     }
-}
+}