yii2項目實戰-訪問控制過濾器ACF講解

作者:白狼 出處:http://www.manks.top/document/yii2-filter-control.html 本文版權歸作者,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

什麼是訪問控制過濾器?字面上來理解就是訪問授權唄,對一些具體的操作設定一些規則進行權限控制。

當然,這裏的【操作】即是指控制器的action了。

前面我們添加新用戶的時候,不知你可有疑問:爲什麼我們訪問主頁(site/index)就讓我們登錄,但是我們在未登錄的時候卻可以直接添加用戶,訪問用戶列表呢?

下面就請我們今天的主角 AccessControl 登場,噼裏啪啦的鼓掌…

AccessControl其實也就是 yii\filters\AccessControl, 我們下面簡寫爲 ACF 作爲描述。

ACF,訪問控制過濾器,適用於簡單的驗證,面對的對象便是控制器的action。對於一些複雜的驗證方式,我們後面會說到 Role Based Access Control (rbac).

接下來我們就上面拋出的問題進行解析。

有同學要質疑了,創建新用戶的操作,肯定要後臺管理纔可以進行操作,包括列表頁等一系列操作,沒登錄肯定不能訪問啊啊啊。

不急,下面我們就看看如何通過ACF去對 user-backend/* 的系列操作進行授權限制!

打開backend\controller\SiteController.php 我們看到這樣一段代碼

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['login', 'error'],
                    'allow' => true,
                ],
                [
                    'actions' => ['logout', 'index'],
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ],
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'logout' => ['post'],
            ],
        ],
    ];
}

我們發現AccessControl是以行爲behaviors的方式附加在當前控制器。

行爲是啥,我們在配置一文中就開始糾結行爲,行爲說白了,他就是一個類,通過某些操作,跟現有的類就行了一個綁定。

既然是綁定,自然就是你(行爲類)可以用我的(當前類),我(當前類)也可以用你的(行爲類)。具體細節,還是那句老話,到了該說的時候我們自然會說,現在說太多豈不是跑題了?

迴歸正題,我們看看AccessControl是怎樣發揮作用的。

不妨打開yii\filters\AccessControl.php文件,init方法中我們看到 配置項rules在使用之前,都會被創建爲 yii\filters\AccessRule 的對象。

也就是說我們實際的配置應該是這樣的

'rules' => [
    [
        'class' => 'yii\filters\AccessRule',
        'actions' => ['login', 'error'],
        'allow' => true,
    ],
],

通過配置一文,很容易就猜到 這裏的actions和allow就是 AccessRule的屬性了。

接着我們看到實際的請求過濾是在beforeAction中進行的!也就是說,在beforeAction中加了一層過濾的條件規則!

如此一來,整個過濾的流程你是不是感覺到清晰了好多,但是還沒有完,我們還沒有說具體的過濾規則,從init方法中,我們瞭解到具體的規則即是 yii\filters\AccessRule 類的屬性了。也就是說,規則怎麼寫,就要看你怎麼設定accessRule的屬性了!屬性怎麼設置?打開 yii\filters\AccessRule文件,看每一個具體的註解!這裏就不說了,因爲註解已經寫得非常詳細了,說多了自然就累贅,不好不好。

那接下來我們就解決問題,UserBackendController/* 所有的操作應該都設置爲登錄之後纔可以操作

'access' => [
    'class' => AccessControl::className(),
    'rules' => [
        [
            // 當前rule將會針對這裏設置的actions起作用,如果actions不設置,默認就是當前控制器的所有操作
            'actions' => ['index', 'view', 'create', 'update', 'delete', 'signup'],
            // 設置actions的操作是允許訪問還是拒絕訪問
            'allow' => true,
            // @ 當前規則針對認證過的用戶; ? 所有方可均可訪問
            'roles' => ['@'],
        ],
    ],
],

我們再做幾個小練習

1、假設index操作只允許post請求才可以訪問

'access' => [
    'class' => AccessControl::className(),
    'rules' => [
        [
            // 當前rule將會針對這裏設置的actions起作用,如果actions不設置,默認就是當前控制器的所有操作
            'actions' => ['view', 'create', 'update', 'delete', 'signup'],
            // 設置actions的操作是允許訪問還是拒絕訪問
            'allow' => true,
            // @ 當前規則針對認證過的用戶; ? 所有方可均可訪問
            'roles' => ['@'],
        ],
        [
            'actions' => ['index'],
        'allow' => true,
            // 設置只允許操作的action
            'verbs' => ['POST'],
        ],
    ],
],

我們新增加的一條規則,設置了AccessRule::verbs屬性即可。

注意哦,ACF 自上向下逐一檢查規則,直到匹配到一個規則。也就是說如果你這裏把verbs的actions index也添加一份到上面的那一條規則,verbs這條規則就相當於廢掉了!

2、假設更新操作update只有用戶test1可以訪問,其他用戶不可以訪問

我們現在只有一個用戶test1, 爲了實現命題,在添加一個新用戶test2

'access' => [
    'class' => AccessControl::className(),
    'rules' => [
        [
            // 當前rule將會針對這裏設置的actions起作用,如果actions不設置,默認就是當前控制器的所有操作
            'actions' => ['index', 'view', 'create', 'delete', 'signup'],
            // 設置actions的操作是允許訪問還是拒絕訪問
            'allow' => true,
            // @ 當前規則針對認證過的用戶; ? 所有用戶均可訪問
            'roles' => ['@'],
        ],
        [
            'actions' => ['update'],
            // 自定義一個規則,返回true表示滿足該規則,可以訪問,false表示不滿足規則,也就不可以訪問actions裏面的操作啦
            'matchCallback' => function ($rule, $action) {
                return Yii::$app->user->id == 1 ? true : false;
            },
            'allow' => true,
        ],
    ],
],

然後你可以通過test1和test2兩個賬號測試,會發現只有test1纔可以訪問update方法,test2就不允許對其進行訪問了。

注:用戶test1的userId等於1,用戶test2的userId等於2

最後,我們不僅學會了ACF,也對user-backend/* 操作進行了部署。

思考一個問題,如果說我們的管理平臺有100個controller, 每個controller有10個action, 如何處理這個授權的問題?如果又要限制某些用戶(注意哦,某些可以指用戶組)對某些操作有權限訪問,另外一些不允許訪問又該如何操作?

有人不怕麻煩:那我就加100個AccessControl, 然後第二個問題就寫matchCallback, 這種答案簡直就是在作死!

下一章,我們來簡單瞭解下相對而言更強大一點的權限控制,基於角色的訪問控制(rbac),敬請期待吧。

[考慮目前國內網站大部分採集文章十分頻繁,更有甚者不註明原文出處,原作者更希望看客們查看原文,以防有任何問題不能更新所有文章,避免誤導!]

查看原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章