I am doing an app that requires authentication. In the index page of the app, I specified access rules like this
public function accessRules() {
return array(
array('deny',
'actions'=>array('index','register','login','password'),
'users'=>array('@'),
),
array('allow',
'users'=>array('*')
),
);
}
At the first rule, the actions 'index','register','login' and 'password' are made unaccessible to authenticated users. However, I do not want to show this message
Unauthorized
You are not authorized to perform this action.
You do not have the proper credential to access this page.
If you think this is a server error, please contact the webmaster.
...to the authenticated users when they try to access those actions. Instead, I want to redirect them to another page. It would be useful if i could do something like this at the first rule
array('redirect',
'actions'=>array('index','register','login','password'),
'users'=>array('@'),
'url'=>array('home/index'),
),
$request->redirect($app->createUrl($rule->redirect));
Should be:
They 'll make you an offer you can't refuse
Starting with Yii v1.1.11
CAccessRule
defines thedeniedCallback
property that easily allows you to define a redirect when access is denied. I don't want to steal Iain Gray's thunder, so go upvote his answer (thanks to the commenter who alerted me to this as well).The original answer follows.
Option 1: extend Yii to enable this functionality (correct)
To do this we will need to write our own classes to be used instead of
CAccessRule
andCAccessControlFilter
. ForCAccessRule
we just need to add one additional property:For
CAccessControlFilter
we want to make it recognize the value of this property and act upon it. To do this, we need to override thepreFilter
method. Starting from the stock implementation, make a few changes:Then we also need to override the
setRules
method, to instruct the filter to use theMyAccessRule
class instead of the standardCAccessRule
. Again, we modify the stock implementation by changing the lineto read
After creating these classes, we have to also inject them into Yii's pipeline. To do this, override
filterAccessControl
on the base controller class; again, taking the stock implementation as reference and making a small change:That's it! You can now take advantage of the extra functionality in any controller by supplying the new
redirect
parameter to the access control filters like this:Option 2: implement access control inside each action (to be avoided)
If you are not comfortable with subclassing Yii's core components, another option that I do not recommend is to embed both access control and redirection logic inside each controller action that you want to protect, or overriding the
beforeAction
method on your controllers to cover multiple actions from one location.Since Yii v1.1.11 you can do the same thing with a callback and a closure, and just the default classes:
this one worked for me since yii 1.1.11:
or use a static method in a Class: