Class yii\filters\AccessControl
AccessControl 基於一組規則提供簡單的訪問控制。
AccessControl 是一個操作篩選器。它將檢查其 $rules 查找 匹配當前上下文變量(例如用戶IIp 地址、用戶角色)的第一條規則。 匹配規則將指定是允許還是拒絕訪問所請求的控制器 操作。如果沒有匹配的規則,訪問將被拒絕。
要使用 AccessControl,請在控制器類的 behaviors()
方法中聲明它。 例如,以下聲明將允許經過身份驗證的用戶訪問 "create" 和 "update" 操作並拒絕所有其他用戶訪問這兩個操作。
public functionbehaviors(){ return [ 'access' => [ 'class' => \yii\filters\AccessControl::className(), 'only' => ['create', 'update'], 'rules' => [ // deny all POST requests [ 'allow' => false, 'verbs' => ['POST'] ], // allow authenticated users [ 'allow' => true, 'roles' => ['@'], ], // everything else is denied ], ], ]; }
公共屬性
屬性 | 類型 | 描述 | 被定義在 |
---|---|---|---|
$denyCallback | callable | 在拒絕當前用戶訪問時將調用的回調。 如果沒有匹配的規則或者是符合以下條件的規則,則會出現這種情況 $allow 設置成 如果未設置,denyAccess() 將會被調用。 回調的簽名應如下所示:
|
yii\filters\AccessControl |
$except | array | 列出所有不需要啟用過濾規則的action ID 如:['index1','index2'] 表示:這兩個方法不進行規則驗證,所有用戶,所有狀態都能訪問 |
yii\base\ActionFilter |
$only | array | 列出所有需要啟用過濾規則的action ID。 如:['index1','index2','index3'] 表示: 如果用戶訪問index方法,那么不進行身份驗證,所有用戶,所有狀態都能訪問 |
yii\base\ActionFilter |
$owner | yii\base\Component|null | The owner of this behavior | yii\base\Behavior |
$ruleConfig | array | 訪問規則的默認配置。單個規則配置 在配置規則的相同屬性時 via $rules 將優先。 | yii\filters\AccessControl |
$rules | array | 訪問規則對象的列表或用於創建規則對象的配置數組。 如果規則是通過配置數組指定的, 它將首先與 $ruleConfig 合並 在用於創建規則對象之前。 |
yii\filters\AccessControl |
$user | yii\web\User|array|string|false | 表示用戶應用程序組件的身份驗證狀態或ID的用戶對象。 從版本 2. | yii\filters\AccessControl |
公共方法
方法 | 描述 | 被定義在 |
---|---|---|
__call() | Calls the named method which is not a class method. | yii\base\BaseObject |
__construct() | Constructor. | yii\base\BaseObject |
__get() | Returns the value of an object property. | yii\base\BaseObject |
__isset() | Checks if a property is set, i.e. defined and not null. | yii\base\BaseObject |
__set() | Sets value of an object property. | yii\base\BaseObject |
__unset() | Sets an object property to null. | yii\base\BaseObject |
afterAction() | 執行動作后立即調用此方法。 您可以覆蓋此方法以對操作執行一些后處理。 | yii\base\ActionFilter |
afterFilter() | yii\base\ActionFilter | |
attach() | Attaches the behavior object to the component. | yii\base\Behavior |
beforeAction() | 此方法是在執行操作之前(在所有可能的篩選器之后。)調用 您可以重寫此方法以便為操作做最后一刻的准備。 | yii\filters\AccessControl |
beforeFilter() | yii\base\ActionFilter | |
canGetProperty() | Returns a value indicating whether a property can be read. | yii\base\BaseObject |
canSetProperty() | Returns a value indicating whether a property can be set. | yii\base\BaseObject |
className() | Returns the fully qualified name of this class. | yii\base\BaseObject |
detach() | Detaches the behavior object from the component. | yii\base\Behavior |
events() | Declares event handlers for the $owner's events. | yii\base\Behavior |
hasMethod() | Returns a value indicating whether a method is defined. | yii\base\BaseObject |
hasProperty() | Returns a value indicating whether a property is defined. | yii\base\BaseObject |
init() | 通過從配置實例化規則對象來初始化 $rules 數組。 | yii\filters\AccessControl |
受保護的方法
方法 | 描述 | 被定義在 |
---|---|---|
denyAccess() | 拒絕用戶訪問。 如果用戶是訪客默認實現會將用戶重定向到登錄頁面; 如果用戶已登錄,則將引發 403 HTTP 異常。 | yii\filters\AccessControl |
getActionId() | 通過將 yii\base\Action::$uniqueId 轉換為相對於模塊的 ID 來返回動作 ID。 | yii\base\ActionFilter |
isActive() | 返回一個值,該值指示過濾器對於給定操作是否處於活動狀態。 | yii\base\ActionFilter |
屬性詳情
在拒絕當前用戶訪問時將調用的回調。 如果沒有匹配的規則或者是符合以下條件的規則,則會出現這種情況 $allow 設置成 false
匹配。 如果未設置,denyAccess() 將會被調用。
回調的簽名應如下所示:
function($rule, $action)
其中 $rule
是拒絕用戶的規則,$action
是當前 action 對象。 如果訪問被拒絕則 $rule
可以為 null
因為所有規則都不匹配。
訪問規則的默認配置。單個規則配置 在配置規則的相同屬性時 via $rules 將優先。
訪問規則對象的列表或用於創建規則對象的配置數組。 如果規則是通過配置數組指定的,它將首先與 $ruleConfig 合並 在用於創建規則對象之前。
參見 [[規則配置]].
表示用戶應用程序組件的身份驗證狀態或ID的用戶對象。 從版本 2.0.2 開始,也可以是用於創建對象的配置數組。 從版本 2.0.12 開始,你可以將其設置為 “false”,以顯式地為篩選器關閉此組件支持。
方法詳情
此方法是在執行操作之前(在所有可能的篩選器之后。)調用 您可以重寫此方法以便為操作做最后一刻的准備。
public boolean beforeAction($action) | ||
$action | yii\base\Action | 要執行的操作。 |
return | boolean | 是否應繼續執行該操作。 |
---|
拒絕用戶訪問。 如果用戶是訪客默認實現會將用戶重定向到登錄頁面; 如果用戶已登錄,則將引發 403 HTTP 異常。
protected void denyAccess($user) | ||
$user | yii\web\User|false | 在分離用戶組件的情況下當前用戶或布爾值 |
throws | yii\web\ForbiddenHttpException | 如果用戶已經登錄或者已分離用戶組件。 |
---|
通過從配置實例化規則對象來初始化 $rules 數組。
public void init() |
授權 ¶
授權是指驗證用戶是否允許做某件事的過程。Yii提供兩種授權方法: 存取控制過濾器(ACF)和基於角色的存取控制(RBAC)。
存取控制過濾器 ¶
存取控制過濾器(ACF)是一種通過 yii\filters\AccessControl 類來實現的簡單授權方法, 非常適用於僅需要簡單的存取控制的應用。正如其名稱所指,ACF 是一種動作過濾器 filter,可在控制器或者模塊中使用。當一個用戶請求一個動作時, ACF會檢查 access rules 列表,判斷該用戶是否允許執 行所請求的動作。
下述代碼展示如何在 site
控制器中使用 ACF:
use yii\web\Controller; use yii\filters\AccessControl; classSiteControllerextendsController{ public functionbehaviors(){ return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['login', 'logout', 'signup'], 'rules' => [ [ 'allow' => true, 'actions' => ['login', 'signup'], 'roles' => ['?'], ], [ 'allow' => true, 'actions' => ['logout'], 'roles' => ['@'], ], ], ], ]; } // ... }
上面的代碼中 ACF 以行為 (behavior) 的形式附加到 site
控制器。 這就是很典型的使用行動過濾器的方法。 only
選項指明 ACF 應當只 對 login
, logout
和 signup
方法起作用。所有其它的 site
控制器中的方法不受存取控制的限制。 rules
選項列出了 存取規則 (access rules),解讀如下:
- 允許所有訪客(還未經認證的用戶)執行
login
和signup
動作。roles
選項包含的問號?
是一個特殊的標識,代表”訪客用戶”。 - 允許已認證用戶執行
logout
動作。@
是另一個特殊標識, 代表”已認證用戶”。
ACF 自頂向下逐一檢查存取規則,直到找到一個與當前 欲執行的動作相符的規則。 然后該匹配規則中的 allow
選項的值用於判定該用戶是否獲得授權。如果沒有找到匹配的規則, 意味着該用戶沒有獲得授權。(譯者注: only
中沒有列出的動作,將無條件獲得授權)
當 ACF 判定一個用戶沒有獲得執行當前動作的授權時,它的默認處理是:
- 如果該用戶是訪客,將調用 yii\web\User::loginRequired() 將用戶的瀏覽器重定向到登錄頁面。
- 如果該用戶是已認證用戶,將拋出一個 yii\web\ForbiddenHttpException 異常。
你可以通過配置 yii\filters\AccessControl::$denyCallback 屬性定制該行為:
[ 'class' => AccessControl::className(), ... 'denyCallback' => function($rule, $action){ throw new \Exception('You are not allowed to access this page'); } ]
Access rules 支持很多的選項。下列是所支持選項的總覽。 你可以派生 yii\filters\AccessRule 來創建自定義的存取規則類。
-
allow: 指定該規則是 "允許" 還是 "拒絕" 。(譯者注:true是允許,false是拒絕)
-
actions:指定該規則用於匹配哪些動作。 它的值應該是動作方法的ID數組。匹配比較是大小寫敏感的。如果該選項為空,或者不使用該選項, 意味着當前規則適用於所有的動作。
-
controllers:指定該規則用於匹配哪些控制器。 它的值應為控制器ID數組。匹配比較是大小寫敏感的。如果該選項為空,或者不使用該選項, 則意味着當前規則適用於所有的動作。(譯者注:這個選項一般是在控制器的自定義父類中使用才有意義)
-
roles:指定該規則用於匹配哪些用戶角色。 系統自帶兩個特殊的角色,通過 yii\web\User::$isGuest 來判斷:
?
: 用於匹配訪客用戶 (未經認證)@
: 用於匹配已認證用戶
使用其他角色名時,將觸發調用 yii\web\User::can(),這時要求 RBAC 的支持 (在下一節中闡述)。 如果該選項為空或者不使用該選項,意味着該規則適用於所有角色。
-
roleParams:指定將傳遞給 yii\web\User::can() 的參數。 請參閱下面描述RBAC規則的部分,了解如何使用它。 如果此選項為空或未設置,則不傳遞任何參數。
-
ips:指定該規則用於匹配哪些 客戶端IP地址 。 IP 地址可在其末尾包含通配符
*
以匹配一批前綴相同的IP地址。 例如,192.168.*
匹配所有192.168.
段的IP地址。 如果該選項為空或者不使用該選項,意味着該規則適用於所有角色。 -
verbs:指定該規則用於匹配哪種請求方法(例如
GET
,POST
)。 這里的匹配大小寫不敏感。 -
matchCallback:指定一個PHP回調函數用於 判定該規則是否滿足條件。(譯者注:此處的回調函數是匿名函數)
-
當這個規則不滿足條件時該函數會被調用。(譯者注:此處的回調函數是匿名函數)
以下例子展示了如何使用 matchCallback
選項, 可使你設計任意的訪問權限檢查邏輯:
use yii\filters\AccessControl; classSiteControllerextendsController{ public functionbehaviors(){ return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['special-callback'], 'rules' => [ [ 'actions' => ['special-callback'], 'allow' => true, 'matchCallback' => function($rule, $action){ return date('d-m') === '31-10'; } ], ], ], ]; } // 匹配的回調函數被調用了!這個頁面只有每年的10月31號能訪問(譯者注:原文在這里說該方法是回調函數不確切,讀者不要和 `matchCallback` 的值即匿名的回調函數混淆理解)。 public functionactionSpecialCallback(){ return $this->render('happy-halloween'); } }
基於角色的存取控制 (RBAC) ¶
基於角色的存取控制 (RBAC) 提供了一個簡單而強大的集中式存取控制機制。 詳細的關於 RBAC 和諸多傳統的存取控制方案對比的詳情,請參閱 Wikipedia。
Yii 實現了通用的分層的 RBAC,遵循的模型是 NIST RBAC model. 它通過 authManager application component 提供 RBAC 功能。
使用 RBAC 涉及到兩部分工作。第一部分是建立授權數據, 而第二部分是使用這些授權數據在需要的地方執行檢查。
為方便后面的講述,這里先介紹一些 RBAC 的基本概念。
基本概念 ¶
角色是 權限 的集合 (例如:建貼、改貼)。一個角色 可以指派給一個或者多個用戶。要檢查某用戶是否有一個特定的權限, 系統會檢查該包含該權限的角色是否指派給了該用戶。
可以用一個規則 rule 與一個角色或者權限關聯。一個規則用一段代碼代表, 規則的執行是在檢查一個用戶是否滿足這個角色或者權限時進行的。例如,"改帖" 的權限 可以使用一個檢查該用戶是否是帖子的創建者的規則。權限檢查中,如果該用戶 不是帖子創建者,那么他(她)將被認為不具有 "改帖"的權限。
角色和權限都可以按層次組織。特定情況下,一個角色可能由其他角色或權限構成, 而權限又由其他的權限構成。Yii 實現了所謂的 局部順序 的層次結構,包含更多的特定的 樹 的層次。 一個角色可以包含一個權限,反之則不行。(譯者注:可理解為角色在上方,權限在下方,從上到下如果碰到權限那么再往下不能出現角色)
配置 RBAC ¶
在開始定義授權數據和執行存取檢查之前,需要先配置應用組件 authManager 。 Yii 提供了兩套授權管理器: yii\rbac\PhpManager 和 yii\rbac\DbManager。前者使用 PHP 腳本存放授權數據, 而后者使用數據庫存放授權數據。 如果你的應用不要求大量的動態角色和權限管理, 你可以考慮使用前者。
使用 PhpManager
¶
以下代碼展示使用 yii\rbac\PhpManager 時如何在應用配置文件中配置 authManager
:
return [ // ... 'components' => [ 'authManager' => [ 'class' => 'yii\rbac\PhpManager', ], // ... ], ];
現在可以通過 \Yii::$app->authManager
訪問 authManager
。
yii\rbac\PhpManager 默認將 RBAC 數據保存在 @app/rbac
目錄下的文件中。 如果權限層次數據在運行時會被修改,需確保WEB服務器進程對該目錄和其中的文件有寫權限。
使用 DbManager
¶
以下代碼展示使用 yii\rbac\DbManager 時如何在應用配置文件中配置 authManager
:
return [ // ... 'components' => [ 'authManager' => [ 'class' => 'yii\rbac\DbManager', // uncomment if you want to cache RBAC items hierarchy // 'cache' => 'cache', ], // ... ], ];
注意: 如果您使用的是 yii2-basic-app 模板,則有一個
config/console.php
配置文件,其中authManager
需要另外聲明在config/web.php
。 在 yii2-advanced-app 的情況下,authManager
只能在common/config/main.php
中聲明一次。
DbManager
使用4個數據庫表存放它的數據:
- itemTable: 該表存放授權條目(譯者注:即角色和權限)。默認表名為 "auth_item" 。
- itemChildTable: 該表存放授權條目的層次關系。默認表名為 "auth_item_child"。
- assignmentTable: 該表存放授權條目對用戶的指派情況。默認表名為 "auth_assignment"。
- ruleTable: 該表存放規則。默認表名為 "auth_rule"。
繼續之前,你需要在數據庫中創建這些表。你可以使用存放在 @yii/rbac/migrations
目錄中的數據庫遷移文件來做這件事(譯者注:根據本人經驗,最好是將授權數據初始化命令也寫到這個 RBAC 數據庫遷移文件中):
yii migrate --migrationPath=@yii/rbac/migrations
閱讀 Separated Migrations 部分中有關處理來自不同名稱空間的遷移的更多信息。
現在可以通過 \Yii::$app->authManager
訪問 authManager
。
建立授權數據 ¶
所有授權數據相關的任務如下:
- 定義角色和權限;
- 建立角色和權限的關系;
- 定義規則;
- 將規則與角色和權限作關聯;
- 指派角色給用戶。
根據授權靈活性要求,上述任務可以通過不同的方式完成。 如果您的權限層次結構僅由開發人員更改,則可以使用遷移或控制台命令。 Migration pro 是可以與其他遷移一起執行的。 控制台命令 pro 是您可以很好地了解代碼中的層次結構, 而不是分散在多個遷移中。
無論哪種方式,最終都會得到以下 RBAC 層次結構:
如果您需要動態形成權限層次結構,則需要 UI 或控制台命令。 用於構建層次結構的 API 本身不會有所不同。
使用遷移(Using migrations) ¶
您可以使用 migrations 通過 authManager
提供的 API 初始化和修改層次結構。
使用 ./yii migrate/create init_rbac
創建新遷移,然后實現創建層次結構:
<?php use yii\db\Migration; classm170124_084304_init_rbacextendsMigration{ public functionup(){ $auth = Yii::$app->authManager; // 添加 "createPost" 權限 $createPost = $auth->createPermission('createPost'); $createPost->description = 'Create a post'; $auth->add($createPost); // 添加 "updatePost" 權限 $updatePost = $auth->createPermission('updatePost'); $updatePost->description = 'Update post'; $auth->add($updatePost); // 添加 "author" 角色並賦予 "createPost" 權限 $author = $auth->createRole('author'); $auth->add($author); $auth->addChild($author, $createPost); // 添加 "admin" 角色並賦予 "updatePost" // 和 "author" 權限 $admin = $auth->createRole('admin'); $auth->add($admin); $auth->addChild($admin, $updatePost); $auth->addChild($admin, $author); // 為用戶指派角色。其中 1 和 2 是由 IdentityInterface::getId() 返回的id // 通常在你的 User 模型中實現這個函數。 $auth->assign($author, 2); $auth->assign($admin, 1); } public functiondown(){ $auth = Yii::$app->authManager; $auth->removeAll(); } }
如果您不想硬編碼哪些用戶具有某些角色,請不要在遷移中使用
->assign()
調用。 相反,請創建UI或控制台命令來管理分配。
遷移可以通過 yii migrate
使用。
使用控制台命令(Using console command) ¶
如果您的權限層次根本沒有改變,並且您擁有固定數量的用戶, 則可以創建一個控制台命令,它將通過 authManager
提供的 API 初始化授權數據一次:
<?php namespace app\commands; use Yii; use yii\console\Controller; classRbacControllerextendsController{ public functionactionInit(){ $auth = Yii::$app->authManager; $auth->removeAll(); // 添加 "createPost" 權限 $createPost = $auth->createPermission('createPost'); $createPost->description = 'Create a post'; $auth->add($createPost); // 添加 "updatePost" 權限 $updatePost = $auth->createPermission('updatePost'); $updatePost->description = 'Update post'; $auth->add($updatePost); // 添加 "author" 角色並賦予 "createPost" 權限 $author = $auth->createRole('author'); $auth->add($author); $auth->addChild($author, $createPost); // 添加 "admin" 角色並賦予 "updatePost" // 和 "author" 權限 $admin = $auth->createRole('admin'); $auth->add($admin); $auth->addChild($admin, $updatePost); $auth->addChild($admin, $author); // 為用戶指派角色。其中 1 和 2 是由 IdentityInterface::getId() 返回的id // 通常在你的 User 模型中實現這個函數。 $auth->assign($author, 2); $auth->assign($admin, 1); } }
注意: 如果您使用高級模板,則需要將
RbacController
放在console/controllers
目錄中, 並將命名空間更改為console/controllers
。
上面的命令可以通過以下方式從控制台執行:
yii rbac/init
如果您不想硬編碼用戶具有某些角色,請不要將
->assign()
調用放入命令中。 相反,請創建UI或控制台命令來管理分配。
為用戶分配角色(Assigning roles to users) ¶
作者可以創建帖子,管理員可以更新帖子並可以做一切作者都能做的。
如果您的應用程序允許用戶注冊,則需要為這些新用戶分配一次角色。 例如,為了讓所有注冊用戶成為高級項目模板中的作者,您需要修改 frontend\models\SignupForm::signup()
, 如下所示:
public functionsignup(){ if ($this->validate()) { $user = new User(); $user->username = $this->username; $user->email = $this->email; $user->setPassword($this->password); $user->generateAuthKey(); $user->save(false); // 增加了以下三行: $auth = \Yii::$app->authManager; $authorRole = $auth->getRole('author'); $auth->assign($authorRole, $user->getId()); return $user; } return null; }
對於需要動態更新授權數據的復雜訪問控制的應用程序,可能需要使用 authManager
提供的 API 來開發特殊的用戶界面(即管理面板)。
使用規則 (Rules) ¶
如前所述,規則給角色和權限增加額外的約束條件。規則是 yii\rbac\Rule 的派生類。 它需要實現 execute() 方法。在之前我們創建的層次結構中,作者不能編輯自己的帖子,我們來修正這個問題。 首先我們需要一個規則來認證當前用戶是帖子的作者:
namespace app\rbac; use yii\rbac\Rule; use app\models\Post; /** * 檢查 authorID 是否和通過參數傳進來的 user 參數相符 */ classAuthorRuleextendsRule{ public $name = 'isAuthor'; /** * @param string|integer $user 用戶 ID. * @param Item $item 該規則相關的角色或者權限 * @param array $params 傳給 ManagerInterface::checkAccess() 的參數 * @return boolean 代表該規則相關的角色或者權限是否被允許 */ public functionexecute($user, $item, $params){ return isset($params['post']) ? $params['post']->createdBy == $user : false; } }
上述規則檢查 post
是否是 $user
創建的。我們還要在之前的命令中 創建一個特別的權限 updateOwnPost
:
$auth = Yii::$app->authManager; // 添加規則 $rule = new \app\rbac\AuthorRule; $auth->add($rule); // 添加 "updateOwnPost" 權限並與規則關聯 $updateOwnPost = $auth->createPermission('updateOwnPost'); $updateOwnPost->description = 'Update own post'; $updateOwnPost->ruleName = $rule->name; $auth->add($updateOwnPost); // "updateOwnPost" 權限將由 "updatePost" 權限使用 $auth->addChild($updateOwnPost, $updatePost); // 允許 "author" 更新自己的帖子 $auth->addChild($author, $updateOwnPost);
現在我們得到如下層次結構:
存取檢查 ¶
授權數據准備好后,存取檢查簡單到只需要一個方法調用 yii\rbac\ManagerInterface::checkAccess()。 因為大多數存取檢查都是針對當前用戶而言,為方便起見, Yii 提供了一個快捷方法 yii\web\User::can(),可以如下例所示來使用:
if (\Yii::$app->user->can('createPost')) { // 建貼 }
如果當前用戶是 ID=1
的 Jane ,我們從圖中的 createPost
開始,並試圖到達 Jane
。 (譯者注:參照圖中紅色路線所示的建貼授權流程)
為了檢查某用戶是否能更新帖子,我們需要傳遞一個額外的參數,該參數是 AuthorRule
要用的:
if (\Yii::$app->user->can('updatePost', ['post' => $post])) { // 更新帖子 }
下圖所示為當前用戶是 John 時所發生的事情:
我們從圖中的 updatePost
開始,經過 updateOwnPost
。為通過檢查,Authorrule
規則的 execute()
方法應當返回 true
。該方法從 can()
方法調用接收到 $params
參數, 因此它的值是 ['post' => $post]
。如果一切順利,我們會達到指派給 John 的 author
角色。
對於 Jane 來說則更簡單,因為她是管理員:
在您的控制器內部有幾種實現授權的方式。 如果您希望細化權限來分開添加和刪除的訪問權限,那么您需要檢查每個操作的訪問權限。 您可以在每個操作方法中使用上述條件,或使用 yii\filters\AccessControl:
public functionbehaviors(){ return [ 'access' => [ 'class' => AccessControl::className(), 'rules' => [ [ 'allow' => true, 'actions' => ['index'], 'roles' => ['managePost'], ], [ 'allow' => true, 'actions' => ['view'], 'roles' => ['viewPost'], ], [ 'allow' => true, 'actions' => ['create'], 'roles' => ['createPost'], ], [ 'allow' => true, 'actions' => ['update'], 'roles' => ['updatePost'], ], [ 'allow' => true, 'actions' => ['delete'], 'roles' => ['deletePost'], ], ], ], ]; }
如果所有的CRUD操作都是一起管理的,那么使用 managePost
這樣的單一權限並且在 yii\web\Controller::beforeAction() 中檢查它是個好主意。
在上面的例子中,沒有參數與指定的訪問動作的角色一起傳遞,但是在 updatePost
權限的情況下,我們需要傳遞 post
參數才能正常工作。 您可以通過在訪問規則中指定 roleParams 將參數傳遞給 yii\web\User::can():
[ 'allow' => true, 'actions' => ['update'], 'roles' => ['updatePost'], 'roleParams' => function(){ return ['post' => Post::findOne(['id' => Yii::$app->request->get('id')])]; }, ],
在上面的例子中,roleParams 是一個 Closure, 將在檢查訪問規則時進行評估,因此模型只會在需要時加載。 如果創建角色參數是一個簡單的操作,那么您可以指定一個數組,如下所示:
[ 'allow' => true, 'actions' => ['update'], 'roles' => ['updatePost'], 'roleParams' => ['postId' => Yii::$app->request->get('id')]; ],
使用默認角色 ¶
所謂默認角色就是 隱式 地指派給 所有 用戶的角色。不需要調用 yii\rbac\ManagerInterface::assign() 方法做顯示指派,並且授權數據中不包含指派信息。
默認角色通常與一個規則關聯,用以檢查該角色是否符合被檢查的用戶。
默認角色常常用於已經確立了一些角色的指派關系的應用(譯者注:指派關系指的是應用業務邏輯層面, 並非指授權數據的結構)。比如,一個應用的 user 表中有一個 group
字段,代表用戶屬於哪個特權組。 如果每個特權組可以映射到 RBAC 的角色,你就可以采用默認角色自動地為每個用戶指派一個 RBAC 角色。 讓我們用一個例子展示如何做到這一點。
假設在 user 表中,你有一個 group
字段,用 1 代表管理員組,用 2 表示作者組。 你規划兩個 RBAC 角色 admin
和 author
分別對應這兩個組的權限。 你可以這樣設置 RBAC 數據,
namespace app\rbac; use Yii; use yii\rbac\Rule; /** * 檢查是否匹配用戶的組 */ classUserGroupRuleextendsRule{ public $name = 'userGroup'; public functionexecute($user, $item, $params){ if (!Yii::$app->user->isGuest) { $group = Yii::$app->user->identity->group; if ($item->name === 'admin') { return $group == 1; } elseif ($item->name === 'author') { return $group == 1 || $group == 2; } } return false; } }
然后按 in the previous section 中的說明創建自己的 command/migration:
$auth = Yii::$app->authManager; $rule = new \app\rbac\UserGroupRule; $auth->add($rule); $author = $auth->createRole('author'); $author->ruleName = $rule->name; $auth->add($author); // ... 添加$author角色的子項部分代碼 ... (譯者注:省略部分參照之前的控制台命令) $admin = $auth->createRole('admin'); $admin->ruleName = $rule->name; $auth->add($admin); $auth->addChild($admin, $author); // ... 添加$admin角色的子項部分代碼 ... (譯者注:省略部分參照之前的控制台命令)
注意,在上述代碼中,因為 "author" 作為 "admin" 的子角色,當你實現這個規則的 execute()
方法時, 你也需要遵從這個層次結構。這就是為何當角色名為 "author" 的情況下(譯者注:$item->name
就是角色名), execute()
方法在組為 1 或者 2 時均要返回 true (意思是用戶屬於 "admin" 或者 "author" 組 )。
接下來,在配置 authManager
時指定 yii\rbac\BaseManager::$defaultRoles 選項(譯者注:在應用配置文件中的組件部分配置):
return [ // ... 'components' => [ 'authManager' => [ 'class' => 'yii\rbac\PhpManager', 'defaultRoles' => ['admin', 'author'], ], // ... ], ];
現在如果你執行一個存取權限檢查, 判定該規則時, admin
和 author
兩個角色都將會檢查。如果規則返回 true ,意思是角色符合當前用戶。基於上述規則 的實現,意味着如果某用戶的 group
值為 1 , admin
角色將賦予該用戶, 如果 group
值是 2 則將賦予 author
角色。
點此進入 Github 編輯!