# Uso Avançado

## Armazenando ACL para Persistência de Dados

Zend_Acl foi projetado de uma maneira que não requer nenhuma teconologia de backend em particular, como um banco de dados ou servidor de cache, para armazenamento de dados ACL. Sua implementação completamente em PHP permite que ferramentas personalizadas de admnistração sejam construídas sob Zend_Acl com relativa facilidade e flexibilidade. Muitas situações necessitam de alguma forma de manutenção da ACL e Zend_Acl fornece métodos para estabelecer e consultar os controles de acesso de uma aplicação.

O armazenamento dos dados da ACL é uma tarefa deixada para o desenvolvedor, visto que espera-se que os casos de uso possam variar muito de acordo com situações diversas. Por conta de Zend_Acl ser serializável, objetos ACL podem ser serializados com a função serialize() do PHP e o resultado pode ser armazenado em qualquer lugar que o desenvolvedor desejar, como um arquivo, banco de dados ou mecanismo de cache.

## Escrevendo Regras ACL Condicionais com Asserções

Algumas vezes uma regra para permitir ou negar acesso de um papel a um recurso não deve ser absoluta, mas dependente de vários critérios. Por exemplo, suponha que certo acesso deva ser liberado, mas somente entre o horário entre 8h00 e 17h00. Outro exemplo seria negar um acesso por conta de uma requisição vinda de um IP que foi identificado como fonte de abuso. Zend_Acl foi construído para suportar a implementação de regras baseadas em quaisquer condições que o desenvolvedor necessitar.

Zend_Acl fornece suporte para regras condicionais com Zend_Acl_Assert_Interface. Para utilizar a interface de asserção de regra, o desenvolvedor escreve uma classe que implemente o método assert() da interface:

    class CleanIPAssertion implements Zend_Acl_Assert_Interface
    {
        public function assert(Zend_Acl $acl,
                               Zend_Acl_Role_Interface $role = null,
                               Zend_Acl_Resource_Interface $resource = null,
                               $privilege = null)
        {
            return $this->_isCleanIP($_SERVER['REMOTE_ADDR']);
        }

        protected function _isCleanIP($ip)
        {
            // ...
        }
    }

Uma vez que uma classe de asserção está disponível, o desenvolvedor deve fornecer uma instância de classe de asserção ao atribuir regras condicionais. Uma regra criada com uma asserção somente se aplica quando o método de asserção retorna `TRUE`.

    $acl = new Zend_Acl();
    $acl->allow(null, null, null, new CleanIPAssertion());

O código acima cria uma regra condicional que permite acesso a todos os priviégios, para tudo e para todos, exceto quando o IP solicitante está em uma "lista negra". Se a requisição vem de um IP que não é considerado "confiável" a regra não se aplicará. Um vez que a regra se aplica a todos os papéis, todos os recursos e todos os privilégios, um IP "não confiável" resultará em uma recusa de acesso. Contudo, este é um caso especial, e deve ser entendido que para todos os outros casos (ex., quando um papel específico, recurso ou privilégio é especificado para a regra), um asserção falsa resultará na regra não sendo aplicada, e outras regras serão utilizadas para determinar se o acesso é permitido ou negado.

Ao método assert() de um objeto de asserção é passada a ACL, o papel, recurso e privilégio de que a consulta de autorização (ex., isAllowed()) se aplica, a fim de fornecer um contexto para que a classe de asserção possa determinar se suas condições são necessárias.