ACF ( Access Control Filter)
ACF ( Access Control Filter)官网的解释就是一个可以在模型或控制器执行行为过滤器,当有用户请求时,ACF将检查access rules (权限规则),在决定是否让这个用户请求这个行为。
在控制器中使用
public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'delete' => ['POST'], ], ], //ACF过滤 'access' => [ 'class' => AccessControl::className(), 'rules' => [ [ //是否云允许 相符合匹配规则 roles 执行这些动作 'allow' => true, //可执行的动作 'actions' => ['login', 'index', 'error'], ///游客未经认证 'roles' => ['?'], ], [ 'allow' => true, //可执行的动作
'actions' => ['logout', 'index','view','update'], // 已认证用户 'roles' => ['@'], ], ], ] ]; }
当ACF知道当前用户没有权限执行当前动作时,他将执行如下默认行为:
如果用户是游客,将调用 yiiwebUser::loginRequired()跳转到登录页面。
如果用户已经是授权用户,它将抛出异常(yiiwebForbiddenHttpException.)。
同时也可以通过配置yiifiltersAccessControl::$denyCallback属性进行自定义这个行为,如下。
[ 'class' => AccessControl::className(), ... 'denyCallback' => function ($rule, $action) { throw new Exception('You are not allowed to access this page'); } ]
同时还支持很多选项,如下列表,也可以扩张 yiifiltersAccessRule来建立自己的自定义权限规则类
allow 指定是否允许或不允许这个规则
actions 动作的匹配规则,值是一个数组,比较是区分大小写。如果这个选项没有设置或为空,那么规则适合所有动作
controllers 指定控制器的匹配规则,值是一个数组
roles 指定匹配的用户角色,有两个角色是公认的,通过yiiwebUser::$isGues进行验证。?匹配未授权用户,@匹配授权用户
ips 用户的IP地址
verbs 指定匹配请求方式(get or post )
matchCallback 指定一个回调判断规则是否匹配
denyCallback 指定一个回调,当规则不匹配时进行调用
use yiifiltersAccessControl; 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'); } }
Role Based Access Control (RBAC)——基于角色存取控制权
配置RBAC
Yii提供两种类型的认证管理,即yii bacPhpManager and yii bacDbManager,前者用PHP脚本文件存储认证数据,后者用数据库存储认证数据。
Using PhpManager
在应用配置中添加 yii bacPhpManager类
return [ // ... 'components' => [ 'authManager' => [ 'class' => 'yii bacPhpManager', ], // ... ], ];
authManager现在能通过 Yii::$app->authManager进行认证
yii bacPhpManager存储RBAC数据文件默认是在@app/rbac目录下,若果权限结构需要被改动,那要确保这个目录可写
Using DbManager
在应用配置中添加 yii bacDbManager类
return [ // ... 'components' => [ 'authManager' => [ 'class' => 'yii bacDbManager', ], // ... ], ];
DbManager会使用四张表存储数据
auth_item 权限表
auth_item_child 权限结构表
auth_assignment 权限分配表
auth_rule 权限规则表
使用 如下命令在@yii/rbac/migrations目录生成文件
yii migrate --migrationPath=@yii/rbac/migrations
建立认证数据
如果权限结构准备好了,如下,那么就可以创建在控制台执行的命令,执行 yii rbac/init 将生成数据
namespace consolecontrollers; use Yii; use yiiconsoleController; class RbacController extends Controller { public function actionInit() { $auth = Yii::$app->authManager; // 添加 "createPost" 权限 $createPost = $auth->createPermission('createPost'); $createPost->description = '新增文章'; $auth->add($createPost); // 添加 "updatePost" 权限 $updatePost = $auth->createPermission('updatePost'); $updatePost->description = '修改文章'; $auth->add($updatePost); // 添加 "deletePost" 权限 $deletePost = $auth->createPermission('deletePost'); $deletePost->description = '删除文章'; $auth->add($deletePost); // 添加 "approveComment" 权限 $approveComment = $auth->createPermission('approveComment'); $approveComment->description = '审核评论'; $auth->add($approveComment); // 添加 "postadmin" 角色并赋予 "updatePost" “deletePost” “createPost” $postAdmin = $auth->createRole('postAdmin'); $postAdmin->description = '文章管理员'; $auth->add($postAdmin); $auth->addChild($postAdmin, $updatePost); $auth->addChild($postAdmin, $createPost); $auth->addChild($postAdmin, $deletePost); // 添加 "postOperator" 角色并赋予 “deletePost” $postOperator = $auth->createRole('postOperator'); $postOperator->description = '文章操作员'; $auth->add($postOperator); $auth->addChild($postOperator, $deletePost); // 添加 "commentAuditor" 角色并赋予 “approveComment” $commentAuditor = $auth->createRole('commentAuditor'); $commentAuditor->description = '评论审核员'; $auth->add($commentAuditor); $auth->addChild($commentAuditor, $approveComment); // 添加 "admin" 角色并赋予所有其他角色拥有的权限 $admin = $auth->createRole('admin'); $commentAuditor->description = '系统管理员'; $auth->add($admin); $auth->addChild($admin, $postAdmin); $auth->addChild($admin, $commentAuditor); // 为用户指派角色。其中 1 和 2 是由 IdentityInterface::getId() 返回的id (译者注:user表的id) // 通常在你的 User 模型中实现这个函数。 $auth->assign($admin, 1); $auth->assign($postAdmin, 2); $auth->assign($postOperator, 3); $auth->assign($commentAuditor, 4); }
权限验证
if (Yii::$app->user->can('createPost')) { // 如果用户用权限 执行 createPost 操作 do something }
如果想让所有的注册用户拥有某一个权限,在高级模板中可以修改 frontendmodelsSignupForm::signup()中代码,如下
public function signup() { if ($this->validate()) { $user = new User(); $user->username = $this->username; $user->email = $this->email; $user->setPassword($this->password); $user->generateAuthKey(); $user->save(false); // the following three lines were added: $auth = Yii::$app->authManager; $authorRole = $auth->getRole('author'); $auth->assign($authorRole, $user->getId()); return $user; } return null; }
Using Rules
规则就是添加额外的约束添加限制角色和权限,一个规则是继承于yii bacRule,因此必须要实现execute()方法。在之前创建的author角色是不能编辑自己的文章,因此来验证下
namespace app bac; use yii bacRule; /** * Checks if authorID matches user passed via params */ class AuthorRule extends Rule { public $name = 'isAuthor'; /** * @param string|int $user the user ID. * @param Item $item the role or permission that this rule is associated with * @param array $params parameters passed to ManagerInterface::checkAccess(). * @return bool a value indicating whether the rule permits the role or permission it is associated with. */ public function execute($user, $item, $params) { return isset($params['post']) ? $params['post']->createdBy == $user : false; } }
添加额外规则
$auth = Yii::$app->authManager; // add the rule $rule = new app bacAuthorRule; $auth->add($rule); // add the "updateOwnPost" permission and associate the rule with it. $updateOwnPost = $auth->createPermission('updateOwnPost'); $updateOwnPost->description = 'Update own post'; $updateOwnPost->ruleName = $rule->name; $auth->add($updateOwnPost); // "updateOwnPost" will be used from "updatePost" $auth->addChild($updateOwnPost, $updatePost); // allow "author" to update their own posts $auth->addChild($author, $updateOwnPost);
Check Accessing
第一种使用
if (Yii::$app->user->can('createPost')) { // create post }
第二种,直接添加在自动验证机制中(behaviors)
public function behaviors() { 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'], ], ], ], ]; }