验证和受权(Authentication and Authorization)php
对于须要限制某些用户访问的网页,咱们须要使用验证(Authentication)和受权(Authorization)。 验证是指核查一我的是否真的是他本身所声称的那我的。这一般须要一个用户名和密码, 但也包括任何其余能够代表身份的方式,例如一个智能卡,指纹等等。 受权则是找出已经过验证的用户是否容许操做特定的资源。 这通常是经过查询此用户是否属于一个有权访问该资源的角色来判断的。html
Yii 有一个内置的验证/受权(auth)框架,用起来很方便,还能对其进行自定义,使其符合特殊的需求。mysql
Yii auth 框架的核心是一个预约义的 用户(user)应用组件 它是一个实现了 IWebUser 接口的对象。 此用户组件表明当前用户的持久性认证信息。咱们能够经过Yii::app()->user
在任何地方访问它。react
使用此用户组件,咱们能够经过 CWebUser::isGuest 检查检查一个用户是否登录; 能够 登陆(login) 或 注销(logout) 一个用户;咱们能够经过CWebUser::checkAccess检查此用户是否能够执行特定的操做;还能够获取此用户的惟一标识(unique identifier)及其余持久性身份信息。web
为了验证一个用户,咱们定义一个有验证逻辑的身份类。这个身份类实现IUserIdentity 接口。sql
不一样的类可能实现不一样的验证方式(例如:OpenID,LDAP)。最好是继承 CUserIdentity,此类是居于用户名和密码的验证方式。数据库
定义身份类的主要工做是实现IUserIdentity::authenticate方法。在用户会话中根据须要,身份类可能须要定义别的身份信息express
下面的例子,咱们使用Active Record来验证提供的用户名、密码和数据库的用户表是否吻合。咱们经过重写getId
函数来返回验证过程当中得到的_id
变量(缺省的实现则是返回用户名)。在验证过程当中,咱们还借助CBaseUserIdentity::setState函数把得到的title
信息存成一个状态。api
authenticate()
to use the database to validate credentials.CUserIdentity::getId()
method to return the _id
property because the default implementation returns the username as the ID.setState()
(CBaseUserIdentity::setState) method to demonstrate storing other information that can easily be retrieved upon subsequent requests.class UserIdentity extends CUserIdentity { private $_id; public function authenticate() { $record=User::model()->findByAttributes(array('username'=>$this->username)); if($record===null) $this->errorCode=self::ERROR_USERNAME_INVALID; else if($record->password!==md5($this->password)) $this->errorCode=self::ERROR_PASSWORD_INVALID; else { $this->_id=$record->id; $this->setState('title', $record->title); $this->errorCode=self::ERROR_NONE; } return !$this->errorCode; } public function getId() { return $this->_id; } }
做为状态存储的信息(经过调用CBaseUserIdentity::setState)将被传递给CWebUser。然后者则把这些信息存放在一个永久存储媒介上(如session)。咱们能够把这些信息看成CWebUser的属性来使用。例如,为了得到当前用户的title
信息,咱们可使用Yii::app()->user->title
(这项功能是在1.0.3版本引入的。在以前的版本里,咱们须要使用Yii::app()->user->getState('title')
)。数组
提示: 缺省状况下,CWebUser用session来存储用户身份信息。若是容许基于cookie方式登陆(经过设置 CWebUser::allowAutoLogin为 true),用户身份信息将被存放在cookie中。确记敏感信息不要存放(例如 password) 。
使用身份类和用户部件,咱们方便的实现登陆和注销。
// 使用提供的用户名和密码登陆用户
$identity=new UserIdentity($username,$password);
if($identity->authenticate())
Yii::app()->user->login($identity);
else
echo $identity->errorMessage;
......
// 注销当前用户
Yii::app()->user->logout();
Here we are creating a new UserIdentity object and passing in the authentication credentials (i.e. the$username
and $password
values submitted by the user) to its constructor. We then simply call theauthenticate()
method. If successful, we pass the identity information into the CWebUser::login method, which will store the identity information into persistent storage (PHP session by default) for retrieval upon subsequent requests. If the authentication fails, we can interrogate the errorMessage
property for more information as to why it failed.
Whether or not a user has been authenticated can easily be checked throughout the application by usingYii::app()->user->isGuest
. If using persistent storage like session (the default) and/or a cookie (discussed below) to store the identity information, the user can remain logged in upon subsequent requests. In this case, we don't need to use the UserIdentity class and the entire login process upon each request. Rather CWebUser will automatically take care of loading the identity information from this persistent storage and will use it to determine whether Yii::app()->user->isGuest
returns true or false.
缺省状况下,用户将根据session configuration完成一序列inactivity动做后注销。设置用户部件的allowAutoLogin属性为true和在CWebUser::login方法中设置一个持续时间参数来改变这个行为。即便用户关闭浏览器,此用户将保留用户登录状态时间为被设置的持续时间之久。前提是用户的浏览器接受cookies。
// 保留用户登录状态时间7天
// 确保用户部件的allowAutoLogin被设置为true。
Yii::app()->user->login($identity,3600*24*7);
As we mentioned above, when cookie-based login is enabled, the states stored via CBaseUserIdentity::setStatewill be saved in the cookie as well. The next time when the user is logged in, these states will be read from the cookie and made accessible via Yii::app()->user
.
Although Yii has measures to prevent the state cookie from being tampered on the client side, we strongly suggest that security sensitive information be not stored as states. Instead, these information should be restored on the server side by reading from some persistent storage on the server side (e.g. database).
In addition, for any serious Web applications, we recommend using the following strategy to enhance the security of cookie-based login.
When a user successfully logs in by filling out a login form, we generate and store a random key in both the cookie state and in persistent storage on server side (e.g. database).
Upon a subsequent request, when the user authentication is being done via the cookie information, we compare the two copies of this random key and ensure a match before logging in the user.
If the user logs in via the login form again, the key needs to be re-generated.
By using the above strategy, we eliminate the possibility that a user may re-use an old state cookie which may contain outdated state information.
To implement the above strategy, we need to override the following two methods:
CUserIdentity::authenticate(): this is where the real authentication is performed. If the user is authenticated, we should re-generate a new random key, and store it in the database as well as in the identity states via CBaseUserIdentity::setState.
CWebUser::beforeLogin(): this is called when a user is being logged in. We should check if the key obtained from the state cookie is the same as the one from the database.
访问控制过滤器是检查当前用户是否能执行访问的controller action的初步受权模式。这种受权模式基于用户名,客户IP地址和访问类型。 It is provided as a filter named as "accessControl".
小贴士: 访问控制过滤器适用于简单的验证。须要复杂的访问控制,须要使用将要讲解到的基于角色访问控制(role-based access (RBAC)).
class PostController extends Controller { public function filters() { return array( 'accessControl', // perform access control for CRUD operations 'postOnly + delete', // we only allow deletion via POST request ); } /** * Specifies the access control rules. * This method is used by the 'accessControl' filter. * @return array access control rules */ public function accessRules() { return array( array('allow', // allow all users to perform 'list' and 'show' actions 'actions'=>array('index','view'), 'users'=>array('*'), ), array('allow', // allow authenticated users to perform any action 'users'=>array('@'), ), array('deny', // deny all users 'users'=>array('*'), ), ); }
访问规则经过以下的上下文参数设置:
actions: 设置哪一个动做匹配此规则。
users: 设置哪一个用户匹配此规则。 此当前用户的name 被用来匹配. 三种设定字符在这里能够用:
*
: 任何用户,包括匿名和验证经过的用户。?
: 匿名用户。@
: 验证经过的用户。roles: 设定哪一个角色匹配此规则。 这里用到了将在后面描述的role-based access control技术。In particular, the rule is applied if CWebUser::checkAccess returns true for one of the roles.提示,用户角色应该被设置成allow
规则,由于角色表明能作某些事情。
ips: 设定哪一个客户端IP匹配此规则。
verbs: 设定哪一种请求类型(例如:GET
, POST
)匹配此规则。
expression: 设定一个PHP表达式。它的值用来代表这条规则是否适用。在表达式,你可使用一个叫$user
的变量,它表明的是Yii::app()->user
。这个选项是在1.0.3版本里引入的。
当受权失败,即,用户不容许执行此动做,如下的两种可能将会产生:
若是用户没有登陆和在用户部件中配置了loginUrl,浏览器将重定位网页到此配置URL。
不然一个错误代码401的HTTP例外将显示。
当配置loginUrl 属性,能够用相对和绝对URL。还可使用数组经过CWebApplication::createUrl来生成URL。第一个元素将设置route 为登陆控制器动做,其余为名-值成对形式的GET参数。以下,
array( ...... 'components'=>array( 'user'=>array( // 这其实是默认值 'loginUrl'=>array('site/login'), ), ), )
若是浏览器重定位到登陆页面,并且登陆成功,咱们将重定位浏览器到引发验证失败的页面。咱们怎么知道这个值呢?咱们能够经过用户部件的returnUrl 属性得到。咱们所以能够用以下执行重定向:
Yii::app()->request->redirect(Yii::app()->user->returnUrl);
基于角色的访问控制提供了一种简单而又强大的集中访问控制。 请参阅维基文章了解更多详细的RBAC与其余较传统的访问控制模式的比较。
Yii 经过其 authManager 组件实现了分等级的 RBAC 结构。 在下文中,咱们将首先介绍在此结构中用到的主要概念。而后讲解怎样定义用于受权的数据。在最后,咱们看看如何利用这些受权数据执行访问检查。
在 Yii 的 RBAC 中,一个基本的概念是 受权项目(authorization item)。 一个受权项目就是一个作某件事的许可(例如新帖发布,用户管理)。根据其粒度和目标受众, 受权项目可分为 操做(operations),任务(tasks)和 角色(roles)。 一个角色由若干任务组成,一个任务由若干操做组成, 而一个操做就是一个许可,不可再分。 例如,咱们有一个系统,它有一个 管理员
角色,它由 帖子管理
和 用户管理
任务组成。 用户管理
任务能够包含 建立用户
,修改用户
和 删除用户
操做组成。 为保持灵活性,Yii 还容许一个角色包含其余角色或操做,一个任务能够包含其余操做,一个操做能够包括其余操做。
受权项目是经过它的名字惟一识别的。
一个受权项目可能与一个 业务规则 关联。 业务规则是一段 PHP 代码,在进行涉及受权项目的访问检查时将会被执行。 仅在执行返回 true 时,用户才会被视为拥有此受权项目所表明的权限许可。 例如,当定义一个updatePost(更新帖子)
操做时,咱们能够添加一个检查当前用户 ID 是否与此帖子的做者 ID 相同的业务规则, 这样,只有做者本身才有更新帖子的权限。
经过受权项目,咱们能够构建一个 受权等级体系 。在等级体系中,若是项目 A
由另外的项目 B
组成(或者说 A
继承了 B
所表明的权限),则 A
就是 B
的父项目。 一个受权项目能够有多个子项目,也能够有多个父项目。所以,受权等级体系是一个偏序图(partial-order graph)结构而不是一种树状结构。 在这种等级体系中,角色项目位于最顶层,操做项目位于最底层,而任务项目位于二者之间。
一旦有了受权等级体系,咱们就能够将此体系中的角色分配给用户。 而一个用户一旦被赋予一个角色,他就会拥有此角色所表明的权限。 例如,若是咱们赋予一个用户 管理员
的角色,他就会拥有管理员的权限,包括 帖子管理
和 用户管理
(以及相应的操做,例如 建立用户
)。
如今有趣的部分开始了,在一个控制器动做中,咱们想检查当前用户是否能够删除指定的帖子。 利用 RBAC 等级体系和分配,能够很容易作到这一点。以下:
if(Yii::app()->user->checkAccess('deletePost')) { // 删除此帖 }
在咱们准备定义一个受权等级体系并执行访问权限检查以前, 咱们须要配置一下 authManager 应用组件。 Yii 提供了两种受权管理器: CPhpAuthManager 和 CDbAuthManager。前者将受权数据存储在一个 PHP 脚本文件中然后者存储在数据库中。 配置 authManager 应用组件时,咱们须要指定使用哪一个受权管理器组件类, 以及所选受权管理器组件的初始化属性值。例如:
return array( 'components'=>array( 'db'=>array( 'class'=>'CDbConnection', 'connectionString'=>'sqlite:path/to/file.db', ), 'authManager'=>array( 'class'=>'CDbAuthManager', 'connectionID'=>'db', ), ), );
而后,咱们即可以使用 Yii::app()->authManager
访问 authManager 应用组件。
定义受权等级体总共分三步:定义受权项目,创建受权项目之间的关系,还要分配角色给用户。 authManager 应用组件提供了用于完成这三项任务的一系列 API 。
要定义一个受权项目,可调用下列方法之一,具体取决于项目的类型:
创建受权项目以后,咱们就能够调用下列方法创建受权项目之间的关系:
最后,咱们调用下列方法将角色分配给用户。
下面的代码演示了使用 Yii 提供的 API 构建一个受权体系的例子:
$auth=Yii::app()->authManager; $auth->createOperation('createPost','create a post'); $auth->createOperation('readPost','read a post'); $auth->createOperation('updatePost','update a post'); $auth->createOperation('deletePost','delete a post'); $bizRule='return Yii::app()->user->id==$params["post"]->authID;'; $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule); $task->addChild('updatePost'); $role=$auth->createRole('reader'); $role->addChild('readPost'); $role=$auth->createRole('author'); $role->addChild('reader'); $role->addChild('createPost'); $role->addChild('updateOwnPost'); $role=$auth->createRole('editor'); $role->addChild('reader'); $role->addChild('updatePost'); $role=$auth->createRole('admin'); $role->addChild('editor'); $role->addChild('author'); $role->addChild('deletePost'); $auth->assign('reader','readerA'); $auth->assign('author','authorB'); $auth->assign('editor','editorC'); $auth->assign('admin','adminD');
创建此受权等级体系后,authManager 组件(例如 CPhpAuthManager, CDbAuthManager) 就会自动加载受权项目。所以,咱们只须要运行上述代码一次,并不须要在每一个请求中都要运行。
信息: 上面的示例看起来比较冗长拖沓,它主要用于演示的目的。 开发者一般须要开发一些用于管理的用户界面,这样最终用户能够经过界面更直观地创建一个受权等级体系。
在定义受权等级体系时,咱们能够将 业务规则 关联到一个角色,一个任务,或者一个操做。 咱们也能够在为一个用户分配角色时关联一个业务规则。 一个业务规则就是一段 PHP 代码,在咱们执行权限检查时被执行。 代码返回的值用来决定是否将角色或分配应用到当前用户。 在上面的例子中,咱们把一条业务规则关联到了updateOwnPost
任务。 在业务规则中,咱们简单的检查了当前用户的 ID 是否与指定帖子的做者 ID 相同。$params
数组中的帖子(post)信息由开发者在执行权限检查时提供。
要执行权限检查,咱们首先须要知道受权项目的名字。 例如,要检查当前用户是否能够建立帖子,咱们须要检查他是否拥有 createPost
所表示的权限。 而后咱们调用 CWebUser::checkAccess 执行权限检查:
if(Yii::app()->user->checkAccess('createPost')) { // 建立帖子 }
若是受权规则关联了一条须要额外参数的业务规则,咱们也能够传递给它。例如,要检查一个用户是否能够更新帖子, 咱们能够经过 $params
传递帖子的数据:
$params=array('post'=>$post); if(Yii::app()->user->checkAccess('updateOwnPost',$params)) { // 更新帖子 }
注意: 默认角色功能从 1.0.3 版本起可用。
许多 Web 程序须要一些能够分配给系统中全部或大多数用户的比较特殊的角色。 例如,咱们可能想要分配一些权限给全部已经过身份验证的用户。若是咱们特地指定并存储这些角色分配,就会引发不少维护上的麻烦。 咱们能够利用 默认角色 解决这个问题。
默认角色就是一个隐式分配给每一个用户的角色,这些用户包括经过身份验证的用户和游客。 咱们不须要显式地将其分配给一个用户。 当 CWebUser::checkAccess 被调用时,将会首先检查默认的角色,就像它已经被分配给这个用户同样。
默认角色必须定义在 CAuthManager::defaultRoles 属性中。 例如,下面的配置声明了两个角色为默认角色:authenticated
和 guest
。
return array( 'components'=>array( 'authManager'=>array( 'class'=>'CDbAuthManager', 'defaultRoles'=>array('authenticated', 'guest'), ), ), );
因为默认角色会被分配给每一个用户,它通常须要关联一个业务规则以肯定角色是否真的要应用到用户。 例如,下面的代码定义了两个角色, authenticated
和 guest
,很高效地分别应用到了已经过身份验证的用户和游客用户。
$bizRule='return !Yii::app()->user->isGuest;'; $auth->createRole('authenticated', 'authenticated user', $bizRule); $bizRule='return Yii::app()->user->isGuest;'; $auth->createRole('guest', 'guest user', $bizRule);
http://blog.sina.com.cn/s/blog_907043b30101emfk.html
如何建立数据库已经role-base
yii下,filters()和accessControl()是YII基本的访问控制体系,
public function filters(){
return array(
'accessControl',
);
}
public function accessControl(){
return array(
array(
'allow', //allow or deny 容许或者拒绝
'controllers' => array('controllersList'), //对控制器进行访问控制
'actions' => array('actionsList'), //对action进行访问控制
'users' => array('usersList'), //对用户
'roles' => array('roles'), //对角色
'ips' => array('ip 地址'), //对客户端地址
'verbs' => array('GET','POST'), //对客户端的请求方式
'expression' => '' //对表达式(通常是业务逻辑)
'message' => 'thank your access', //错误信息提示,通常是deny时用到
),
array(....),
....
array('deny', users => array('*')),
);
}
好了,有了以上的访问控制,咱们针对上面的roles进行讨论RBAC。
Yii的RBAC是基于一个组件authManager的,能够先在main。php中配置authManager
authManger分为基于数据库的和基于PHP脚本的,通常若是你的应用程序基于数据库(mysql或者pgsql),最好把authManger配置为CDbAuthManger,而不是CPhpAuthManger。
...
'authManager' => array(
'class' => 'CDbAuthManager',
'connectionID' => 'db',
),
'db' => array(...),
...
配置好了之后,须要在数据库中增长3个存放RBAC规则的表:
AuthItem -- 存放创建的受权项目(role、task或者opration)
AuthItemChild -- 存放受权项目的继承关系
AuthAssignMent -- 存放用户和受权项目的关系表
CREATE TABLE `authitem` ( `name` varchar(64) NOT NULL, `type` int(11) NOT NULL, `description` text, `bizrule` text, `data` text, PRIMARY KEY (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `authitemchild` ( `parent` varchar(64) NOT NULL, `child` varchar(64) NOT NULL, PRIMARY KEY (`parent`,`child`), KEY `child` (`child`), CONSTRAINT `authitemchild_ibfk_1` FOREIGN KEY (`parent`) REFERENCES `authitem` (`name`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `authitemchild_ibfk_2` FOREIGN KEY (`child`) REFERENCES `authitem` (`name`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `authassignment` ( `itemname` varchar(64) NOT NULL, `userid` varchar(64) NOT NULL, `bizrule` text, `data` text, PRIMARY KEY (`itemname`,`userid`), CONSTRAINT `authassignment_ibfk_1` FOREIGN KEY (`itemname`) REFERENCES `authitem` (`name`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
建好表之后,就能够用Yii提供的authManger组件的API创建相关的受权项目,并指定受权关系了。
下面是一个例子:
下面作一个实例:
class AuthManagerController extends Controller { public function actionIndex(){ $auth = Yii::app()->authManager; if ($auth !== NULL){ $auth->clearAll(); //create roles $roleOwner = $auth->createRole('owner'); $roleReader = $auth->createRole('reader'); $roleMember = $auth->createRole('member'); $roleBlackList = $auth->createRole('blackList'); //create operations //issues $auth->createOperation('createIssue', 'create issue in project'); $auth->createOperation('readIssue', 'read issue'); $auth->createOperation('updateIssue', 'update issue'); $auth->createOperation('deleteIssue', 'delete issue'); //projects $auth->createOperation('createProject', 'create a new project'); $auth->createOperation('readProject', 'read project'); $auth->createOperation('updateProject', 'update project'); $auth->createOperation('deleteProject', 'delete project'); //users $auth->createOperation('createUser', 'create a new user'); $auth->createOperation('readUser', 'read user'); $auth->createOperation('updateUser', 'update user'); $auth->createOperation('deleteUser', 'delete user'); //authorization $roleReader->addChild('readIssue'); $roleReader->addChild('readProject'); $roleReader->addChild('readUser'); $roleMember->addChild('reader'); $roleMember->addChild('createIssue'); $roleMember->addChild('updateIssue'); $roleMember->addChild('deleteIssue'); $roleOwner->addChild('reader'); $roleOwner->addChild('member'); $roleOwner->addChild('createProject'); $roleOwner->addChild('updateProject'); $roleOwner->addChild('deleteProject'); $roleOwner->addChild('createUser'); $roleOwner->addChild('updateUser'); $roleOwner->addChild('deleteUser'); //assign //此时,在Issue中的rules中设置view和index的roles=>array('member'),无论是什么用户,都没法访问这两个action $userAdmin = User::model()->findByAttributes(array('username' => 'admin')); $auth->assign('owner', $userAdmin->id); $auth->assign('member', $userAdmin->id); //将用户名为admin(id=3)指定为member角色,这样就能够访问了。 $auth->assign('reader', $userAdmin->id); $userDemo = User::model()->findByAttributes(array('username' => 'demo')); $auth->assign('member', $userDemo->id); //将用户名为admin(id=3)指定为member角色,这样就能够访问了。 $auth->assign('reader', $userDemo->id); //将用户名为demo(id=4)指定为reader角色 $userDemo2 = User::model()->findByAttributes(array('username' => 'demo2')); $auth->assign('reader', $userDemo2->id); //将用户名为demo(id=4)指定为reader角色 $userBlackList = User::model()->findByAttributes(array('username' => 'demo3')); $auth->assign('blackList', $userBlackList->id); }else{ $message = 'Please config your authManage as a compontion in main.php'; throw new CHttpException(0, $message); } } }
执行上面的文件,创建受权关系之后,更新accessRules为: public function accessRules() { return array( array('allow', // allow all users to perform 'index' and 'view' actions 'actions'=>array('index','view'), 'users'=>array('@'), 'roles' => array('member', 'owner', 'reader'), ), array('allow', // allow authenticated user to perform 'create' and 'update' actions 'actions'=>array('create','update'), 'users'=>array('@'), 'roles' => array('member', 'owner'), ), array('allow', // allow admin user to perform 'admin' and 'delete' actions 'actions'=>array('admin','delete'), 'users'=>array('@'), 'roles' => array('owner'), ), array('deny', // deny all users 'users'=>array('*'), ), ); } 就是把刚刚创建的受权项目加入到访问控制列表中。
另一个例子 $auth = Yii::app()->authManger; $roleManager = $auth->createRole('manager'); //创建一个角色 $auth->createTask('projectManager'); //创建任务 $auth->createTask('userManager'); $auth->createOpration('createProject'); //创建操做 $auth->createOpration('updateProject'); $auth->createOpration('deleteUser'); $user = User::model()->findByPk('1'); //检索用户 $roleManager->addChild('projectManager'); //为角色受权任务 $roleManager->addChild('updateProject');//为角色受权操做 $auth->assign('manager', $user->id);//指定用户权限
转自:http://blog.chinaunix.net/uid-395468-id-185860.html
-------------------------------------------------------------------------------------
YII非rbac通用权限,controller中加权限过滤器beforeaction
public function purview($module, $control, $action) { if (!$this->checkPower($action, $control, module)) { throw new CHttpException(403, '您没有访问权限!'); Yii::app()->end(); } } // CGRIDVIEW buttonID 'visible' =>'$this->grid->controller->checkPower("delete")', public function checkPower($action, $contrl = null, $module = null) { if ($contrl === null) { $contrl = $this->getId(); } if ($module === null && $this->getModule()) { $module = $this->getModule()->getId(); } return Privilege::model()->checkPower($module, $contrl, $action); } public function beforeAction($action) { $contrl = $this->getId(); $actionId = $action->getId(); $route = $contrl . '/' . $actionId; if (!in_array($route, array('site/login', 'site/error', 'site/logout')) && Yii::app()->user->id != 1) { $module = null; if ($action && $this->getModule()) { $module = $this->getModule()->getId(); } $this->purview($module, $contrl, $actionId); } return parent::beforeAction($action); }
在这里的visible表达式中设置调用$this->checkPower('操做名');就能够隐藏没有权限访问的菜单了
上面的好像有问题,为何还要调用parent::beforeAction呢,直接返回ture和false就能够。返回true就执行。
----------------------------------
一篇文章:
开始准备
Yii提供了强大的配置机制和不少现成的类库。在Yii中使用RBAC是很简单的,彻底不须要再写RBAC代码。因此准备工做就是,打开编辑器,跟我来。
设置参数、创建数据库
在配置数组中,增长如下内容:
那这三个数据表怎么创建呢?很简单,去看framework/web/auth/schema.sql。注意要和你的自定义的表名称对应起来。好比SQL文件中的AuthItem你要修改成pre_auth_item。而后在数据库中运行这个SQL文件中的语句。
了解概念
你可能要问,剩下的代码呢?我告诉你,没有啦。RBAC系统就这样创建起来了。可是为了使用它,你须要了解它的运行机制。我会尽可能讲的啰嗦一点……(官方的RBAC文档在这里,可是我曾经看了4-5遍才明白。)
三个概念
你须要了解的是,受权项目可分为operations(行动),tasks(任务)和 roles(角色)。
一个用户拥有一个或者多个角色,好比,咱们这里有三个角色:银行行长、银行职员、顾客。咱们假设:
* 张行长 有角色:银行行长、银行职员、顾客(人家本身能够存钱嘛)。
* 王职员 有角色:银行职员、顾客。
* 小李 有角色:顾客。
那么,相应的,只要顾客能够作的事情,小李就能够作,王职员和张行长也能够。银行职员能够作的事情,王职员和张行长均可以作,小李就不能够了。
好比,一个“顾客”能够存钱,那么拥有“顾客”角色的张行长、王职员、小李均可以存钱。“银行职员”能够打印顾客的交易记录,那么有“银行职员”角色的张行长和王职员均可以,而小李不行,必须找一个有“银行职员”角色的人才能够打印详细的交易记录。一个“银行行长”才能够进入银行钱库提钱,那么只有张行长能够,由于它才有“银行行长”的角色。
这就是基于角色的认证体系,简称RBAC。
角色的继承
角色是能够继承的,好比咱们规定以下:
* 凡是“银行行长”都是“银行职员”,也就是说,只要银行职员能够作的事情,银行行长均可以作。
* 凡是“银行职员”都是顾客,同上,顾客能够作的事情银行职员也能够作。
那么角色关系就变成了:
* 张行长 有角色:银行行长。
* 王职员 有角色:银行职员。
* 小李 有角色:顾客。
这样更简单了,这就是角色的继承。
任务的继承
一个任务(task)是能够包含另一个任务的,咱们举个例子,好比“进入银行”。
咱们设定“顾客”这个角色有“进入银行”的权限。也就是说,“顾客”能够执行“进入银行”的任务。接下来,咱们假设“进入柜台”是进入银行的父权限,也就是说,“进入柜台”包含“进入银行”。只要能“进入柜台”的人均可以“进入银行”。咱们把“进入柜台”这个任务权限给“银行职员”。
那么从角色上来讲,王职员能够进入银行,由于王职员的角色是“银行职员”,而“银行职员”包含了“顾客”的角色。那么“顾客”能够进行的“任务”对于“银行职员”来讲也是能够进行的。而“顾客”能够“进入银行”,那么王职员也能够“进入银行”。这是角色的继承带来的。
咱们再假设有个赵领导,是上级领导,能够进入柜台进行视察。那么,咱们的任务关系是:
* 赵领导 有任务:进入柜台。
那么,赵领导就能够“进入银行”。由于“进入银行”是被“进入柜台”包含的任务。只要能够执行“进入柜台”的人均可以执行“进入银行”。这就是任务的继承。
关于行动
行动是不可划分的一级。也就是说。而一个行动是不能包含其余行动的。假设咱们有个行动叫“从银行仓库中提钱”。咱们把这个行动做包含“进入柜台”。那么只要能够执行“从银行仓库中提钱”的角色均可以执行“进入柜台”这个任务。
三者关系
* 一个角色能够包含另一个或者几个角色。
* 一个角色能够包含另一个或者几个任务。
* 一个角色能够包含另一个或者几个行动。
*
* 一个任务能够包含另一个或者几个任务。
* 一个任务能够包含另一个或者几个行动。
*
* 一个行动只能被角色或者任务包含,行动是不能够包含其余,也不可再分。
这样,就造成了一个权限管理体系。关于“任务”和“行动”,你没必要思考其字面上的意义。这二者就是造成两层权限。
进行赋权
咱们创建了RBAC权限管理,就须要进行对权限的WEB管理。这些就须要你本身写代码了。
根据不一样种类的项目调用下列方法之必定义受权项目:
* CAuthManager::createRole
* CAuthManager::createTask
* CAuthManager::createOperation
一旦咱们拥有一套受权项目,咱们能够调用如下方法创建受权项目关系:
* CAuthManager::addItemChild
* CAuthManager::removeItemChild
* CAuthItem::addChild
* CAuthItem::removeChild
最后,咱们调用下列方法来分配角色项目给各个用户:
* CAuthManager::assign
* CAuthManager::revoke
下面咱们将展现一个例子是关于用所提供的API创建一个受权等级:
也就是说,你须要本身写一个管理界面,来列出你的角色、任务、行动,而后能够在这个界面上进行管理。好比增长、删除、修改。
权限检查
假设你在你的管理界面进行了赋权,那么能够在程序里面进行权限检查:
上面的代码就检查了用户是否能够执行“createPost”,这createPost多是一个任务,也能够是一个行动。
其余的
对于不少说Yii权限体系RBAC很差用的人其实都没有看懂文档。综合个人体验,我感受Yii框架的RBAC是我用过的框架里面最好用的。并且是须要本身写代码最少的。
Yii的RBAC有更加高级的用法,好比“业务规则”,“默认角色”。你能够去参考官方文档。
我知道,会有部分人仍旧不理解RBAC,或者不会用Yii的RBAC。没有关系,你能够在下方的评论框里提问。
happy Yii !
------------------------------------------------------------------------
。虽然authMangner组件实现了rbac,可是没有实现可视化编辑管理。目前官方有Srbac 和 Right两个比较好的扩展模块,咱们用它们很是方便的可视化管理角色(roles),任务(tasks),操做(operations)。
参考:http://blog.sina.com.cn/s/blog_92863deb01014ac0.html
http://www.howzhi.com/course/2519/lesson/35392
http://www.open-open.com/lib/view/open1356679026838.html
http://www.cnblogs.com/hi-bazinga/archive/2012/05/15/2502194.html