If you need to display different versions of the index page (i.e. use different controllers), depending on whether a user is a guest or not, you may use the following code: (add this to config/main.php)
'onBeginRequest' => function () {
if (!Yii::app()->user->isGuest) {
Yii::app()->defaultController = 'dashboard';
}
},
As nwap noticed, a guest user can easily access DashboardController by simply typing "index.php?r=dashboard/index". The solution is to forbid access of unauthorized users to DashboardController by using access filters:
class DashboardController extends Controller
{
public function filters ()
{
return array(
'accessControl',
);
}
public function accessRules ()
{
// allow only authenticated users
return array(
array('allow',
'users' => array('@'),
),
array('deny',
'users' => array('?'),
),
);
}
/** the rest of the code */
}
I think your suggestion is Yii’s “standard” solution
However, I am trying to setup a webapp where only a few select pages are accessible by ‘Guest’. The rest require an authorized user for access.
I’d like a solution that satisfies the following goals:
If I forget to do something (such as update the accessRules() method on a new controller), I want the safe default behavior. In other words deny access to ‘Guest’.
If access is denied to ‘Guest’, I want Yii to redirect to the login page instead of showing an error.
I’ve come up with a solution that satisfies these goals, but since I’m very new to Yii, I’m looking for feedback and/or suggestions from the Yii community.
Here are the changes that I made:
In the array returned by ‘protected/config/main.php’, I added a params[‘publicPages’] entry:
'params'=>array(
...
// List of public pages that can be accessed without authentication.
// All other pages will result in a redirect to the login page.
'publicPages'=>array(
'site/login',
'site/error',
),
),
In ‘protected/components/Controller.php’, I overrode the runActionWithFilters() method:
/**
* Runs an action with the specified filters.
* Extends the CController::runActionWithFilters() function.
* If a Guest user is trying to access a non-public page, then redirect to the login page.
* @param CAction $action the action to be executed.
* @param array $filters list of filters to be applied to the action.
*/
public function runActionWithFilters($action,$filters)
{
$params=Yii::app()->params;
if(isset($params) && isset($params['publicPages']))
{
$route="{$this->id}/{$action->id}";
if (!in_array($route, $params['publicPages']))
{
if (Yii::app()->user->isGuest)
{
Yii::app()->user->loginRequired();
return;
}
}
}
parent::runActionWithFilters($action,$filters);
}
Seems to work for me on v1.1.7 and v1.1.8 – Please comment.
However, that is the whole point. As stated in my #1 goal, for websites where most of the pages require some type of authorization, I want the default behavior to block all pages without having to write the same code in every controller and/or every action.
I do not understand how using access rules satisfies my original #1 goal: