yii\filters\AccessControl 訪問權限控制


Class yii\filters\AccessControl

 
繼承 yii\filters\AccessControl » yii\base\ActionFilter » yii\base\Behavior » yii\base\BaseObject
實現 yii\base\Configurable
可用版本自 2.0
源碼 https://github.com/yiichina/yii2/blob/api/framework/filters/AccessControl.php

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 設置成 false 匹配。

如果未設置,denyAccess() 將會被調用。

回調的簽名應如下所示: `php function ($rule, $action) ` 其中 $rule 是拒絕用戶的規則,

$action 是當前 action 對象。 如果訪問被拒絕則 $rule 可以為 null 因為所有規則都不匹配。

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

屬性詳情

$denyCallback 公共 屬性

在拒絕當前用戶訪問時將調用的回調。 如果沒有匹配的規則或者是符合以下條件的規則,則會出現這種情況 $allow 設置成 false 匹配。 如果未設置,denyAccess() 將會被調用。

回調的簽名應如下所示:

function($rule, $action)

其中 $rule 是拒絕用戶的規則,$action 是當前 action 對象。 如果訪問被拒絕則 $rule 可以為 null 因為所有規則都不匹配。

public callable $denyCallback null
$ruleConfig 公共 屬性

訪問規則的默認配置。單個規則配置 在配置規則的相同屬性時 via $rules 將優先。

public array $ruleConfig = ['class' => 'yii\filters\AccessRule']
$rules 公共 屬性

訪問規則對象的列表或用於創建規則對象的配置數組。 如果規則是通過配置數組指定的,它將首先與 $ruleConfig 合並 在用於創建規則對象之前。

參見 [[規則配置]].

public array $rules = []
$user 公共 屬性

表示用戶應用程序組件的身份驗證狀態或ID的用戶對象。 從版本 2.0.2 開始,也可以是用於創建對象的配置數組。 從版本 2.0.12 開始,你可以將其設置為 “false”,以顯式地為篩選器關閉此組件支持。

public yii\web\User|array|string|false $user 'user'

方法詳情

beforeAction() 公共 方法

此方法是在執行操作之前(在所有可能的篩選器之后。)調用 您可以重寫此方法以便為操作做最后一刻的准備。

public boolean beforeAction($action)
$action yii\base\Action

要執行的操作。

return boolean

是否應繼續執行該操作。

denyAccess() 受保護 方法

拒絕用戶訪問。 如果用戶是訪客默認實現會將用戶重定向到登錄頁面; 如果用戶已登錄,則將引發 403 HTTP 異常。

protected void denyAccess($user)
$user yii\web\User|false

在分離用戶組件的情況下當前用戶或布爾值 false

throws yii\web\ForbiddenHttpException

如果用戶已經登錄或者已分離用戶組件。

init() 公共 方法

通過從配置實例化規則對象來初始化 $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 應當只 對 loginlogoutsignup 方法起作用。所有其它的 site 控制器中的方法不受存取控制的限制。 rules 選項列出了 存取規則 (access rules),解讀如下:

  • 允許所有訪客(還未經認證的用戶)執行 loginsignup 動作。 roles 選項包含的問號 ? 是一個特殊的標識,代表”訪客用戶”。
  • 允許已認證用戶執行 logout 動作。@是另一個特殊標識, 代表”已認證用戶”。

ACF 自頂向下逐一檢查存取規則,直到找到一個與當前 欲執行的動作相符的規則。 然后該匹配規則中的 allow 選項的值用於判定該用戶是否獲得授權。如果沒有找到匹配的規則, 意味着該用戶沒有獲得授權。(譯者注: only 中沒有列出的動作,將無條件獲得授權)

當 ACF 判定一個用戶沒有獲得執行當前動作的授權時,它的默認處理是:

你可以通過配置 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:指定該規則用於匹配哪種請求方法(例如GETPOST)。 這里的匹配大小寫不敏感。

  • 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\PhpManageryii\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 層次結構:

Simple RBAC hierarchy

如果您需要動態形成權限層次結構,則需要 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); 

現在我們得到如下層次結構:

RBAC hierarchy with a rule

存取檢查

授權數據准備好后,存取檢查簡單到只需要一個方法調用 yii\rbac\ManagerInterface::checkAccess()。 因為大多數存取檢查都是針對當前用戶而言,為方便起見, Yii 提供了一個快捷方法 yii\web\User::can(),可以如下例所示來使用:

if (\Yii::$app->user->can('createPost')) { // 建貼 } 

如果當前用戶是 ID=1 的 Jane ,我們從圖中的 createPost 開始,並試圖到達 Jane 。 (譯者注:參照圖中紅色路線所示的建貼授權流程)

Access check

為了檢查某用戶是否能更新帖子,我們需要傳遞一個額外的參數,該參數是 AuthorRule 要用的:

if (\Yii::$app->user->can('updatePost', ['post' => $post])) { // 更新帖子 } 

下圖所示為當前用戶是 John 時所發生的事情:

Access check

我們從圖中的 updatePost 開始,經過 updateOwnPost。為通過檢查,Authorrule 規則的 execute() 方法應當返回 true 。該方法從 can() 方法調用接收到 $params 參數, 因此它的值是 ['post' => $post] 。如果一切順利,我們會達到指派給 John 的 author 角色。

對於 Jane 來說則更簡單,因為她是管理員:

Access check

在您的控制器內部有幾種實現授權的方式。 如果您希望細化權限來分開添加和刪除的訪問權限,那么您需要檢查每個操作的訪問權限。 您可以在每個操作方法中使用上述條件,或使用 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 角色 adminauthor 分別對應這兩個組的權限。 你可以這樣設置 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'], ], // ... ], ]; 

現在如果你執行一個存取權限檢查, 判定該規則時, adminauthor 兩個角色都將會檢查。如果規則返回 true ,意思是角色符合當前用戶。基於上述規則 的實現,意味着如果某用戶的 group 值為 1 , admin 角色將賦予該用戶, 如果 group 值是 2 則將賦予 author 角色。

億速雲
發現錯別字或您認為此頁面需要改進?
點此進入 Github 編輯!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM