yiiのアクセス制御を学ぶ CDbAuthManager導入の巻
ロールベースアクセスコントロール(RBAC)を導入するのは面倒で後回しにしてきました。ロールのデザイン、ロール管理の実装、ユーザー管理の実装、権限付与の実装には時間がかかりそうで躊躇してしまうのです。そこでこれらをできる限り省略してRBACを導入することにフォーカスしてみます。
これからやることが想像できない場合はロールベースアクセスコントロールを読む。やりたいことはなんとなくわかった、でもなんだか面倒だなーと思うくらいでOK。とりあえずやってみる。
手順
- アプリケーション作成
- ユーザー管理
- ユーザー認証
- 権限付与マネージャの導入
- ロール管理
- 操作に権限を割り当てる
アプリケーション作成
blogデモを利用します。
ユーザー管理
blogデモにはユーザー管理機能がありません。前のポストを参考にしてもいいですが、とりあえずのユーザー生成スクリプトを用意したので使ってください。
4ユーザー usera, userb, userc, userd のパスワードはすべてdemoです。
INSERT INTO tbl_user (id, username, password, salt, email) VALUES (901, 'usera','2e5c7db760a33498023813489cfadc0b','28b206548469ce62182048fd9cf91760','webmaster@example.com'); INSERT INTO tbl_user (id, username, password, salt, email) VALUES (902, 'userb','2e5c7db760a33498023813489cfadc0b','28b206548469ce62182048fd9cf91760','webmaster@example.com'); INSERT INTO tbl_user (id, username, password, salt, email) VALUES (903, 'userc','2e5c7db760a33498023813489cfadc0b','28b206548469ce62182048fd9cf91760','webmaster@example.com'); INSERT INTO tbl_user (id, username, password, salt, email) VALUES (904, 'userd','2e5c7db760a33498023813489cfadc0b','28b206548469ce62182048fd9cf91760','webmaster@example.com');
ユーザー認証
blogデモに実装済みなのでパス。パス。
権限付与マネージャの導入
権限付与マネージャには CDbAuthManager と CPhpAuthManager がありますが今回使うのは前者です。
CDbAuthManager の設定
- config/main.phpに次を追加する
protected/config/main.php
'components'=>array( 'authManager'=>array( 'class'=>'CDbAuthManager', 'connectionID'=>'db', ), ),
CDbAuthManager が必要とするテーブルを生成
- framework/web/auth/schema-*.sql のスクリプトで作成する
ロール管理
yiiガイドにあるロール構造を登録します。権限付与アイテムとは、ロール構造図をあわせて読むと理解しやすい。
権限付与アイテム
権限付与アイテムとは何かをする許可のことです。(例:新しいブログ記事を作る、ユーザを管理する) 粒度と対象者によって、権限付与アイテムはオペレーション、タスク、ロールに分類されます。 ロールは複数のタスクからなり、タスクは複数のオペレーションからなります。 そして、オペレーションが一番小さな許可単位です。
http://www.yiiframework.com/doc/guide/1.1/ja/topics.auth
ロール構造図
ここのロール構造図を参照。
簡易ロール管理
ロール管理はUIで管理したいところですが、今回は SiteController.phpにロールを初期化/登録するアクションを追加します。追加したら http:/path/to/index.php/site/loadroles にアクセスしロール定義をロードします。
protected/controllers/SiteController.php
<?php public function actionLoadRoles() { $auth=Yii::app()->authManager; // ロール初期化 $auth=Yii::app()->clearAll(); // ロール定義 $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"]->author_id;'; $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule); $task->addChild('updatePost'); $role=$auth->createRole('reader','reader'); $role->addChild('readPost'); $role=$auth->createRole('author','author'); $role->addChild('reader'); $role->addChild('createPost'); $role->addChild('updateOwnPost'); $role=$auth->createRole('editor','editor'); $role->addChild('reader'); $role->addChild('updatePost'); $role=$auth->createRole('admin','admin'); $role->addChild('editor'); $role->addChild('author'); $role->addChild('deletePost'); // ユーザーに権限付与 $auth->assign('reader','1'); //demo $auth->assign('reader','901'); //usera $auth->assign('author','902'); //userb $auth->assign('editor','903'); //userc $auth->assign('admin', '904'); //userd }
ロール作成時、descriptionを設定しました。
各ユーザーの権限
- demo 記事の参照
- usera 記事の参照
- userb 記事の参照と作成 + 自身が作成した記事の編集
- userc 記事の参照と作成と編集
- userd 記事の参照と作成と編集と削除
権限チェック
ここまでできたら次はいよいよユーザーに付与した権限を元にBlogデモが動作するよう改修していきます。ログインユーザーが権限を持っている/いないは CWebUser#checkAccess で得られます。
Yii::app()->user->checkAccess('createPost')
view上で判定する
protected/components/views/userMenu.php
<?php <ul> <?php if (Yii::app()->user->checkAccess('createPost')) : ?> <li><?php echo CHtml::link('Create New Post',array('post/create')); ?></li> <?php endif; ?> <?php if (Yii::app()->user->checkAccess('admin')) : ?> <li><?php echo CHtml::link('Manage Posts',array('post/admin')); ?></li> <?php endif; ?> <?php if (Yii::app()->user->checkAccess('editor')) : ?> <li><?php echo CHtml::link('Approve Comments',array('comment/index')) . ' (' . Comment::model()->pendingCommentCount . ')'; ?></li> <?php endif; ?> <li><?php echo CHtml::link('Logout',array('site/logout')); ?></li> </ul>
Postコントローラーのアクセスコントロールフィルター
protected/controllers/PostController.php
<?php public function accessRules() { return array( array('allow', 'actions'=>array('index','view'), 'roles'=>array('readPost'), ), array('allow', 'actions'=>array('create'), 'roles'=>array('createPost'), ), array('allow', 'actions'=>array('update'), 'roles'=>array('updatePost'), ), array('allow', 'actions'=>array('delete'), 'roles'=>array('deletePost'), ), array('deny', // deny all users 'users'=>array('*'), ), ); }
まとめ
説明しきれていないことが多々あるけれど、CDbAuthManagerは導入できたと思う。
- 権限付与マネージャは CDbAuthManager と CPhpAuthManager がある
- 権限アイテムにはロール、タスク、オペレーションがある。オペレーションが最小単位。
- ロール管理は権限付与マネージャを使う。が、将来的にはyii-Rightsなどのエクステンションを使って管理すると思う
- 権限チェックは CwebUser#checkAccess からできる
- アクセスコントロールフィルターから権限チェックを利用できる