Browsing all articles tagged with Zend_Auth
Jun
3

Ein einfaches ACL System über Zend_Config_Ini

Ich will hier ein knappes und einfaches ACL und Auth System vorstellen, das ich mir gebastelt habe. Natürlich ist es hier sehr viel vereinfachter dargestellt, aber es funktioniert ;)

Erstmal die, welche in meinem Beispiel in /application/configs/ lagert. Dort dürfte es nichts zu erklären geben.

; Die existierenden Rollen angeben
role.0 = "guest"
role.1 = "user"
role.2 = "admin"

; Die existierenden Resourcen angeben
res.0 = "index"
res.1 = "error"
res.2 = "user"
res.3 = "test"

; Nun die genehmigungen für die einzelnen ROllen
access.guest.0 = "index"
access.guest.1 = "error"
access.guest.2 = "user"

access.user.0 = "index"
access.user.1 = "error"
access.user.2 = "user"
access.user.3 = "test"

access.admin.0 = "index"
access.admin.1 = "error"
access.admin.2 = "user"
access.admin.3 = "test"

Dazu gibt es eine Model Datei. Man kann diese natürlich auch anderweitig lagern. Ich habe es aber vorerst so gelöst. Die Klasse erweitert Zend_Acl. Als Parameter kann man den Standort einer Konfigurationsdatei angeben. Standard ist aber der o.g. Pfad. Es wird dann die Konfiguration geladen und in ein Array umgewandelt. Dieses Array wird nun durchgegangen. Die Resourcen angelegt und die Rollen. Wenn es nun für eine Rolle auch Einstellungen gibt, dann werden diese ebenso angelegt. Da Zend_Acl grundsätzlich erstmal alle Resourcen verbietet werden wir auch all jene erlauben, die erlaubt sein dürfen.
Wenn keine passende Konfiguration vorliegt, dann wird eine Zend_Acl_Exception geworfen.

<?php

/**
 * Festlegen der ACL Strukturen
 */
class Model_Acl extends Zend_Acl{

    private $_config;

    public function __construct($config = null){

        if($config != null)
        {
            $this->_config = (string) $config;
        }
        else
        {
            $this->_config = (string) APPLICATION_PATH . "/configs/acl.ini";
        }

        # Ini Datei muss im Construct mitgegebenw erden
       if(file_exists($this->_config))
       {
           # Konfig einlesen und in ein Array wandeln
           $config = new Zend_Config_Ini($this->_config);
           $config = $config->toArray();

            # Die Ressourcen dem ACL Syste4m hinzugüen
           foreach ($config["res"] as $res)
           {
               $this->add(new Zend_Acl_Resource($res));
           }

           # DIe Rollen dem ACL System hinzufügen
           foreach($config["role"] as $role)
           {
               $this->addRole(new Zend_Acl_Role($role));

               # Wenn es zu der Rolle auch was in der Accesslist gibt, dann füge das hinzu
               if(isset($config["access"][$role]))
               {
                   foreach($config["access"][$role] as $access)
                   {
                       $this->allow($role, $access);
                   }
               }
           }
       }
       else
       {
          throw Zend_Acl_Exception('Keine gültige Konfig angegeben!');
       }

    }

}

Irgendwo muss das Acl System aber auch initialisiert werden. Dafür habe ich ein Auth Plugin. In diesem Plugin nutze ich öfters ein Log, das ich mit “firelog” in der Registry benannt habe. Entweder man ändert dies in sein eigenes Log oder nimmt das Logging gänzlich raus. Die ganze Routine läuft nach dem Routing und vor dem Dispatch, damit Controller und Action noch beeinflusst werden können.
Eigentlich sollte das ganze Selbsterklärend sein für jemanden, der zumindest schon ein wenig gelesen hat. Ich empfehle hier das Kapitel Zend_Auth im Reference Guide.
Ansonsten sei nur gesagt, dass zu anlässen wie der nicht funktionierende Login oder das erfolgte einloggen Zielcontroller und Zielaction geändert werden, damit andere Seiten erscheinen. So braucht man sich in den Controllern selbst keine Gedanken mehr über das Auth System machen.

<?php
class Zorta_Plugin_Auth extends Zend_Controller_Plugin_Abstract {

	/**
	 * Nachdem das Routing durchgeführt wurde geht es los mit dem Auth System
	 * @uses Zend_Controller_Request_Abstract
	 */
	public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
	{

        # Lade eine Instanz von Zend_Auth
		$auth = Zend_Auth::getInstance();	

		# Wenn der Request ein POST ist und die Action Login aufgerufen wurde, dann versuche den Login
		if($request->isPost() && $request->getActionName() == "login"){

	        # POST Daten checken
			$username = $request->getParam('username');
			if($username == "")
				$username = "Dummy";

			$userpass = $request->getParam('userpass');
			if($userpass == "")
				$userpass = "Dummy";

			# Zend_DB_Table aus der Registry holen als Datenbankadapter für die Authorisation
			$db = Zend_Registry::get('Zend_Db_Table');
			$adapter = new Zend_Auth_Adapter_DbTable($db,'user','user_name','user_pass','MD5(?)');

			# Username und Passwort setzen
			$adapter->setCredential($userpass);
			$adapter->setIdentity($username);

			# Wenn die Nutzerdaten Ok waren, dann schreibe das Auth in den Storage
			if($auth->authenticate($adapter) && $auth->getIdentity() != false){

				# Schreibe die Identität in die Session
				$auth->getStorage()->write($adapter->getResultRowObject(null, 'password'));

                # Log, dass der Login durchgeführt wurde
				Zend_Registry::get('firelog')->log('Login accomplished!', Zend_Log::INFO);

				# Ab zum Index (Willkommensseite)
				$request->setControllerName('index');
				$request->setActionName('index');

			}
			else
			{

				# Wenn es nicht ok war, log und ab zurück zum Login
				Zend_Registry::get('firelog')->log('Login failed!', Zend_Log::INFO);
				$request->setControllerName('user');
				$request->setActionName('login');
			}
		}

		# Wenn keine Identität vorliegt
		if(!$auth->hasIdentity())
		{
			# Keine Identität, loggen und auf Zugriff prüfen mit der Gruppe "Gast"
			Zend_Registry::get('firelog')->log('User is not logged in!', Zend_Log::INFO);
			$this->testAcl($request, "guest");
		}
		else
		{
		   	# Authorisiert, log und Zugriffsprüfung
			Zend_Registry::get('firelog')->log('User is logged in!', Zend_Log::INFO);
			$this->testAcl($request, $auth->getIdentity()->user_group);
		}

	}

	/**
	 * Methode zum prüfen der Authorisation mittels ACL
	 * @param Zend_Controller_Request_Abstract $request
	 * @param $group Benutzergruppe
	 */
	public function testAcl(Zend_Controller_Request_Abstract $request, $group = null)
	{

	    # Laden der ACL Struktur und erstellen einer Instanz
	    require_once APPLICATION_PATH . '/model/Acl.php';
	    $acl = new Model_Acl();

	    # Prüfe den Status der Zugriffsberechtigung
	    if($acl->isAllowed($group,$request->getControllerName()))
	    {
	        # Wenn die Ressource erlaubt ist
	        Zend_Registry::get('firelog')->log('User has Auth for: '. $request->getControllerName(), Zend_Log::INFO);

	    }
	    else
	    {
	        # Wenn die Resource nicht erlaubt ist
	        Zend_Registry::get('firelog')->log('User has no Auth for: '. $request->getControllerName(), Zend_Log::ALERT);

	        $request->setControllerName('user');
			$request->setActionName('noauth');
	    }
	}
}