Yii 2.0鉴权之访问控制过滤器(Yii2.0 Authorization By ACF)
鉴权就是验证一个用户是否有足够权限去做一件事的过程。
Yii提供了两种鉴权方式:Access Control Filter (ACF,访问控制过滤器)和Role-Based Access Control (RBAC,基于角色的访问控制)。
访问控制过滤器(ACF)
ACF是一种简单的鉴权方式,是用来做一些简单的访问控制的一种好方法。
顾名思义,ACF是作为一个行为(behavior)附加在控制器(controller)或者一个模块(module)上的动作过滤器。ACF会检查一组访问规则,以确认当前用户是否有足够的权限访问动作(action)。
以下代码展示了如何去使用ACF:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use
yii\filters\AccessControl;
class
SiteController
extends
Controller
{
public
function
behaviors()
{
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
动作上面。rules
选项指定了访问规则:
允许所有游客(guest,未认证用户)访问
login
和signup
动作(action),roles
选项是一个问号(?
),代表的就是游客(guests)。允许经过认证的用户访问
logout
动作,字符@
就是指已认证的用户。
当ACF执行鉴权检查的时候,它将从上到下依次检查每条规则(rules),直到找到匹配。allow的值会在最终判断鉴权的时候使用。
假如没有任何规则匹配,那么ACF会终止用户的进一步操作。
默认的,当一个没有通过鉴权的用户访问当前动作(action)时,ACF会这样做:
假如是一个游客,它会调用yii\web\User::loginRequired()方法,重定向浏览器到登录页面。
假如是一个已认证用户,它会抛出一个权限错误的异常yii\web\ForbiddenHttpException。
如果你要自定义ACF的这些默认行为,可以通过配置yii\filters\AccessControl::$denyCallback属性来达到目的:
1
2
3
4
5
6
7
8
[
'class'
=> AccessControl::className(),
'denyCallback'
=>
function
(
$rule
,
$action
) {
throw
new
\Exception(
'You are not allowed to access this page'
);
}
'only'
=> [
'login'
,
'logout'
,
'signup'
],
'rules'
=> ...
]
访问规则支持很多选项,下面是一些简要说明,你也可以通过扩展yii\filters\AccessRule来创建你自己的访问规则类:
allow
:指定这是一条允许(allow)还是拒绝(deny)规则。
actions
:这条规则匹配那些动作(action)。是一个动作ID的数组,区分大小写,假如这个选项设置为空或者不设置,那么这条规则适用于所有动作(action)。
controllers
:指定这条规则适用于那些控制器(controller)。值是控制器ID数组,区分大小写,设置为空或者不设置,意味着适用于所有控制器(controller)。
roles
:指定这条规则适用于那些用户角色。有两个认可的特殊角色,都是通过yii\web\User::$isGuest来检查。?
:匹配游客(未认证用户),@
:匹配已认证的用户,未设置或设为空,则匹配所有角色。
ips
:匹配那些客户端IP。ip地址可以使用通配符(*),比如:192.168.*。为设置或设为空则匹配所有IP。
verbs
:匹配那些请求方式(如:GET,POST)。区分大小写。
matchCallback
:指定一个PHP回调,以确定应用该规则。
denyCallback
:PHP回调,当规则禁止访问的时候会被调用。
下面的例子展示了如何去使用matchCallback选项,允许你写任意的访问检查逻辑:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class
SiteController
extends
Controller
{
public
function
behaviors()
{
return
[
'access'
=> [
'class'
=> AccessControl::className(),
'only'
=> [
'special-callback'
],
'rules'
=> [
[
'actions'
=> [
'special-callback'
],
'allow'
=> true,
'matchCallback'
=>
function
(
$rule
,
$action
) {
return
date
(
'd-m'
) ===
'31-10'
;
}
],
],
],
];
}
// Match callback called! This page can be accessed only each October 31st
public
function
actionSpecialCallback()
{
return
$this
->render(
'happy-halloween'
);
}
}
一个matchCallback形式如下:
function ($rule, $action)
$rule就是这个rule本身,$action就是当前action对象。回调应该返回Boolean值,用来确认这条规则是否要被应用。
一个denyCallback形式如下:
function ($rule, $action)
$rule就是这个rule本身,$action就是当前action对象。