20 października 2009 ~ 2 Komentarzy

ZF #2 Zend_Acl

accesscontrol

Każda większa strona musi posiadać system autoryzacji użytkowników. Zend Framework jest wyposażony w biblioteke pozwalająca zarządzać Rolami, Zasobami oraz Zasadami dostępu do nich. Bilioteka ta zwie się Zend_Acl.

Kod Acl jest łatwy do ponownego wykorzystania w kolejnych aplikacjach, wiec zamiast pisać model w aplikacji często zapisuje go w katalogu /library. Na początku trzeba stworzyć role jakie mają występować w aplikacji, czyli rodzaje użytkowników. Pierwszą Rolą bedzie gość, czyli użytkownik który jeszcze nie zalogował się do aplikacji.

W pliku: library\App\Acl\Roles\Guest.php

<?php
/**
 * Guest Role for Acl
 *
 * @author Nexik
 */
class App_Acl_Role_Guest
  implements Zend_Acl_Role_Interface
{
  public $id = null;
  public $role = 'guest';

  public function getRoleId()
  {
    return $this->role;
  }
}
?>

Kod jest prosty. Implementuje on interfejs Zend_Acl_Role_Interface, aby byliśmy pewni, że przy korzystaniu z Zend_Acl wszystko będzie działać. Następnym rodzajem użytkownika jest zalogowany użytkownik czyli User:)

W pliku: library\App\Acl\Roles\User.php

<?php
/**
 * User Role for Acl
 *
 * @author Nexik
 */
class App_Acl_Role_User
  implements Zend_Acl_Role_Interface
{
  public $id = null;
  public $role = 'user';

  public function getRoleId()
  {
    return $this->role;
  }
}
?>

Jak już role są przygotowane, to należy zarejestrować zasoby w aplikacji. W każdej aplikacji opartej o Zend Framework występuje conajmniej jeden podstawowy zasób czyli IndexController. Oto jak zarejestrować ten zasób.

W pliku: \library\App\Acl.php

<?php
/**
 * Description of Acl
 *
 * @author Nexik
 */
class App_Acl
  extends Zend_Acl
{
  public function __construct()
  {
    // Roles
    $this->addRole(new App_Acl_Role_Guest());
    $this->addRole(new App_Acl_Role_User(), 'guest');

    //Resources
    $this->add(new Zend_Acl_Resource('index'));

    //Rules
  }
}

Na początku dodaliśmy dwie nowe role do naszego Acl’a. Ważna rzecz jest w linii 14, gdzie nie tylko dodaliśmy role User, ale także ustaliliśmy rodzica dla tej roli. Dzięki ustaleniu rodzica dla roli User jako role Guest, User będzie miał wszelkie uprawnienia roli Guest plus te które mu dodatkowo nadamy. Jest to zgodne z zasadą DIY DRY, czyli nie powtarzaj się.

Teraz musimy napisać naże zasady. Aby być pewnym że wszystko pójdzie dobrze zrobimy to w podejściu TDD.

W pliku \tests\library\App\AclTest.php

<?php
/**
 * Description of AclTest
 *
 * @author Nexik
 */
class AclTest
    extends ControllerTestCase
{
  /**
   * instance of Acl object for testing permission in application
   *
   * @var App_Acl
   */
  private $acl;

  /**
   * Array of Role Objects that implements Zend_Acl_Role_Interface
   *
   * @var Array
   */
  private $roles = array();

  /**
   * Basic method that is executed before every test
   */
  public function setUp()
  {
      parent::setUp();
      $this->acl = new App_Acl();
      $this->roles = $this->acl->getRegisteredRoles();
  }

  /**
   * Checks if Guest have proper privileges
   *
   * Guest can view index\index
   */
  public function testGuestAccess()
  {
      $guest = $this->roles['guest']['instance'];

      $this->assertTrue($this->acl->isAllowed($guest, 'index', 'index'));
  }

  /**
   * Checks if User have proper privileges
   *
   * User can view index\index
   */
  public function testUserAccess()
  {
      $user = $this->roles['user']['instance'];

      $this->assertTrue($this->acl->isAllowed($user, 'index', 'index'));
  }
}

Klasa posiada dwa prywatne atrybuty: $acl oraz $roles. $acl przechowuje instancje naszej klasy App_Acl. $roles natomiast przechowuje tablice wszystkich ról zarejestrowanych poprzez App_Acl. Na razie testy są dość proste, jedno przyrównanie na test.

W celu aby testy przeszły musimy zmienić kod w pliku: /library/App/Acl.php:

<?php
/**
 * Description of Acl
 *
 * @author Nexik
 */
class App_Acl
  extends Zend_Acl
{
  public function __construct()
  {
    // Roles
    $this->addRole(new App_Acl_Role_Guest());
    $this->addRole(new App_Acl_Role_User(), 'guest');

    //Resources
    $this->add(new Zend_Acl_Resource('index'));

    //Rules
    $this->allow('guest', 'index', 'index');
  }
}

Dzięki dziedziczeniu musimy dodać tylko linijkę 14.

P.S. W nowej wersji ZF wprowadzono nowy system ładowania bibliotek zewnętrznych. Więc jeżeli chcecie używać powyższego kodu to należy wprowadzić zmiany w pliku: /application/Bootstrap.php:

<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
  protected function _initAutoload()
  {
    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->registerNamespace('App_');
  }
}

Komentarze do wpisu “ZF #2 Zend_Acl”

  1. tasuki 22 stycznia 2010 at 12:34 pm Permalink

    DIY jest Do It Yourself ^^
    nie powtarzaj sie jest DRY … mala roznica ;)

  2. nexik 22 stycznia 2010 at 1:13 pm Permalink

    literówka, mój błąd.
    dzięki za info, poprawione


Dodaj komentarz