<sect1 id="zend.acl.advanced">

    <title>高级用法</title>

    <sect2 id="zend.acl.advanced.storing">

        <title>保存 ACL 数据确保持久性</title>

        <para>
           Zend_Acl 就是这样设计的，它不需要为 ACL 数据的存储而要求任何特别的后台技术如数据库或者缓冲服务器。它的完全的 PHP 实现使得在Zend_Acl之上构建定制的管理工具相当地容易和灵活。许多情形需要一些 ACL 的交互式维护，并且 Zend_Acl 为设定、查询、应用软件的访问控制提供了方法。
        </para>

        <para>
           因为期望应用案例有多种变化来适应不同的情形，ACL 数据的存储因此留给开发者来完成。因为 Zend_Acl 是可序列化的，所以 ACL 的对象可以用 PHP 中的 <ulink url="http://php.net/serialize"><code>serialize()</code></ulink> 函数来序列化，并且结果可以存在开发者所期望的任何地方，例如文件、数据库、或缓存机构。
        </para>

    </sect2>

    <sect2 id="zend.acl.advanced.assertions">

        <title>使用声明(Assert)来编写条件性的 ACL 规则</title>

        <para>
           有时候允许或禁止一个 Role 访问一个 Resource 的规则不是绝对的而是依靠不同的标准。例如，只有在 8：00am 和 5:00pm 之间，特定的访问才被允许。另外一个禁止访问的例子是因为一个请求来自于被标记为不良的 IP 地址。Zend_Acl 对基于无论开发者有什么需要的条件的规则实现有个内置的支持。
        </para>

        <para>
            Zend_Acl 用 <code>Zend_Acl_Assert_Interface</code> 提供支持有条件的规则。为了使用规则声明接口，开发者写了一个实现接口中 <code>assert()</code> 方法的类。
        </para>

        <programlisting role="php"><![CDATA[
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)
    {
        // ...
    }
}}
]]>
        </programlisting>

        <para>
            一旦声明类可用，当分配有条件的规则时，开发者必需提供声明类的一个实例。用声明建立的规则只适用于当声明方法返回 true。
        </para>

        <programlisting role="php"><![CDATA[
$acl = new Zend_Acl();
$acl->allow(null, null, null, new CleanIPAssertion());
]]>
        </programlisting>

        <para>
           上面的代码创建了一个有条件的 allow 规则，它允许所有人对所有资源有所有的访问权限，除非请求的 IP 列在“黑名单”上。如果一个请求来自于一个不是“清白”的 IP, 这个 allow 规则就不适用。因此这个规则适用于所有的 Roles、所有的 Resources 和所有的权限，一个“不清白”的 IP 将导致一个禁止访问。这是一个特例，对于其它所有案例（例如，一个特定的 Role、Resource、或者被指定规则的权限），一个失败的声明将导致规则不适用，并且其它规则将被用于决定访问是被允许或禁止。
        </para>

        <para>
           为了给声明类提供一个上下文环境(Context)来决定所需的条件，Assert对象的 <code>assert()</code> 方法将以ACL、 Role、 Resource 和适用于授权查询（例如<code>isAllowed()</code>）的权限作为参数。
        </para>

    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
