weizhan2008 发表于 2011-12-22 08:54

Yii Framework Access Control Lists

<font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">In my series <a href="http://www.larryullman.com/series/learning-the-yii-framework/" target="_blank" target="_blank"><span style="color:#A00004">Learning the Yii Framework</span></a>, I discuss the
individual parts of the MVC (Model, View, Controller) architecture in some
detail, from a Yii perspective. In the post on <a href="http://www.larryullman.com/2009/11/15/basic-controller-edits-in-yii/" target="_blank" target="_blank"><span style="color:#A00004">Controllers</span></a>, I introduce <i>Access Control
Lists</i> (ACLs), Yii’s default way of restricting who can take what actions.
This is a key part of the security of any Web application. For example, a
site’s content can often be read by anyone at all, registered or non-registered
users alike (like the text you’re reading now). Some content may only be
viewable by registered users and some by registered users of a certain type
(e.g., paid members). Finally, some content may only be viewable by
administrators. In this post, I detail how to completely control access to your
Web application using Yii’s Access Control Lists.To start by repeating what I
wrote in my <a href="http://www.larryullman.com/2009/11/15/basic-controller-edits-in-yii/" target="_blank" target="_blank"><span style="color:#A00004">Basic Controller Edits</span></a> post, a Controller’s <b>accessRules()</b>
method dictates who can do what. In a very simple way, the “what” refers to the
Controller’s action methods, like <b>actionList()</b> or <b>actionDelete()</b>.
In other words, only X type of user can call the <b>actionDelete()</b> method,
which, of course, deletes a record. Your “who” depends upon the situation, but
to start there’s at least logged-in and not logged-in users, represented by <b>*</b>
(anyone) and <b>@</b> (logged-in users), accordingly. Depending upon the login
system in place, you may also have levels of users. So the <b>accessRules()</b>
method uses all this information and returns an array of values. The values are
also arrays, indicating permissions (<i>allow</i> or <i>deny</i>), actions, and
users:</span></font>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">public function accessRules()</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">{</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>return array(</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('allow',<span style="mso-spacerun:yes">&nbsp; </span>// allow all users
to perform 'list' and 'show' actions</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('list','show'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('*'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>array('allow',
// allow authenticated user to perform 'create' and 'update' actions</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('create','update'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('@'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('allow', // allow admin user to perform 'admin' and 'delete' actions</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('admin','delete'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('admin'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('deny',<span style="mso-spacerun:yes">&nbsp; </span>// deny all users</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('*'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>);</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">}</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">That’s the default setting for a Controller, where anyone can perform list
and show actions, meaning that anyone can list all records or show individual
records in an associated Model. The next section allows any logged-in user to
perform create and update actions. Next, only administrators can perform admin
and delete actions. Finally, a global deny for all users is added, to cover any
situation that wasn’t explicitly defined. This is just a good security
practice. Note that these rules just apply to this Controller; each Controller
needs its own rules.</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">So at the most basic level, your access rules begin by allowing or denying
actions to logged-in or non-logged-in users. When you go to create your own
rules, start with what anyone can do and end with what no one can do. For
example, say you have some user management system that includes the Models <b>User</b>
and <b>UserType</b>, corresponding to related tables in the database. The <b>UserType</b>
would be a simple two-field object—<i>id</i> and<i> type</i>, where type might
be <i>reader</i>, <i>writer</i>, <i>editor</i>, and so forth. Each <b>User</b>
then is assigned a single, specific type. I’d be inclined to grant list and
show permissions to everyone, as that might be useful for browsing users by
type and would be necessary for adding new users. However, I probably wouldn’t
allow create, update, admin (which is really a variation on list), or delete
permissions on <b>UserType</b> at all, with the thinking that these are static
values. The <b>accessRules()</b> would then be:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">public function accessRules()</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">{</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>return array(</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('allow',<span style="mso-spacerun:yes">&nbsp; </span>// allow all users
to perform 'list' and 'show' actions</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('list','show'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('*'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('deny', // no one can create, update, or delete these:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('create','update','admin','delete'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('*'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>array('deny',<span style="mso-spacerun:yes">&nbsp; </span>// deny all users
anything not specified</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('*'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>);</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">}</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">As you can see, just to be extra careful, I include a final deny clause
still: if actions are added later the default behavior will be denial; only by
then changing the rules can that action be executed by anyone.</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">To take this beyond logged-in vs. non-logged-in users, you need to know
that the representation of logged-in users relies upon Yii’s authentication
components. In the default rules, the admin user can perform certain actions,
where “admin” is the actual name of the user that is logged in, and comes from <b>protected/components/UserIdentity.php</b>.&nbsp;
I write about the authentication process in detail in two posts: the <a href="http://www.larryullman.com/2010/01/04/simple-authentication-with-the-yii-framework/" target="_blank" target="_blank"><span style="color:#A00004">first covering simple authentication</span></a>, <a href="http://www.larryullman.com/2010/01/07/custom-authentication-using-the-yii-framework/" target="_blank" target="_blank"><span style="color:#A00004">the second covering more evolved authentication</span></a>.
The default Yii application allows for two users, with names of <i>demo</i> and
<i>admin</i>, but you’d likely have a more elaborate system in place. If you
know only a limited number of users will be admins, you could hardcode their
usernames into the rules:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">array('allow', // allow harold and maude user to perform
'admin' and 'delete' actions</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('admin','delete'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('harold','maude'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">),</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">This is still a bit too static, though. Perhaps your users in the database
would be registered by user type, or <i>role</i>, and that the permissions
would be based upon these roles. In that case, you can add an expression
element to the returned array in the access rules:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">array('allow',</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('admin','delete'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;</span><span style="mso-spacerun:yes">&nbsp;&nbsp; </span>'users'=&gt;array('@'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'expression'=&gt;'PHP code to be evaluated'</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">),</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">Two things about this expression. First, you still need to use the <i>users</i>
element, and you’ll probably want to still restrict this to logged-in users
(most likely). Second, the expression itself should be some PHP code, <u>quoted</u>,
that when evaluated gives a Boolean result. If the code in the expression will
be true, then permission will be allowed; false, denied. Say you wanted to
restrict the publish action to only those with the role of editor:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">array('allow',</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'actions'=&gt;array('publish'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'users'=&gt;array('@'),</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;
</span>'expression'=&gt;'isset($user-&gt;role) &amp;&amp;
($user-&gt;role==="editor")'</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">),</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">The <b>$user-&gt;role</b> value would have to be established when the user
logs in, as part of the authentication process. I discuss this exact example in
my <a href="http://www.larryullman.com/2010/01/07/custom-authentication-using-the-yii-framework/" target="_blank" target="_blank"><span style="color:#A00004">second post that covers more evolved authentication</span></a>.
And I put the entire expression within quotes (it doesn’t matter whether you
use single or double, so long as you don’t create a parse error). With that
rule, users that aren’t logged in, or users that are logged in but have
non-editor roles, won’t be able to take that action.</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">A final way in which I’ve enforced authorization in previous Yii projects
involves a bit of a hack. I had a site where users with a certain role could
create certain types of content. They could also update or delete those types
of content, but only if they were the one to create that content in the first
place. In other words, say a user creates an event, then their user ID gets
associated with that event’s record. The update and delete actions in the <b>EventController</b>
should only be executable if the currently-logged-in user’s ID is the same as
the <b>ownerId</b> of the event in question. As far as I know, this cannot be
addressed in the <b>accessRules()</b> method, because those rules are evaluated
prior to the loading of any specific Model. My solution, perhaps a hack but it
works, was to add the proper logic within the actions. Here’s a simplified
version of how that would look within one of the actions:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">public function actionDelete()</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">{</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>$event =
$this-&gt;loadEvents(); // Fetch the specific event Model.</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>// Can only
delete the events they created:</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>if
($event-&gt;ownerId == Yii::app()-&gt;user-&gt;id) {</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>$event-&gt;delete();</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>} else {</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new
CHttpException(403,'Invalid request. You are not allowed to delete this
event.');</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}</span></font></p>

<p class="MsoNormal" style="text-align:left;mso-pagination:widow-orphan;
tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;
mso-font-kerning:0pt" lang="EN-US">}</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">As I said, that’s a hack but it works fine for me and is simple enough to
follow (also, the actions that display events for editing and deleting get
changed to only list those with a matching <b>ownerId</b>). A better solution
would likely be to use <a href="http://www.yiiframework.com/doc/guide/topics.auth#role-based-access-control" target="_blank" target="_blank"><span style="color:#A00004">Yii’s Role-Based Access Control (RBAC)</span></a>. I
haven’t personally gone down that path yet as I haven’t had the need; the above
knowledge has more than sufficed for the sites I’ve created thus far.</span></font></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:
auto;text-align:left;mso-pagination:widow-orphan" align="left"><font size="2"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt" lang="EN-US">As always, thanks for reading and let me know what comments or questions
you may have. Thanks, Larry</span></font></p>

<p class="MsoNormal"><font size="2"><span lang="EN-US">&nbsp;</span></font></p>
页: [1]
查看完整版本: Yii Framework Access Control Lists