3
votes

I'm new in Yii, and I need to fix some thing: there is some controller with some actions, and if user tries to load some action, I need to check if he's authorized; if yes, then do some actions, if no - to redirect to login page. How can I do it? I hope I needn't to check through Yii::user and redirect manually in each action? Thanks in advance.

4
You should read the guide on Authentication & Authorization. Apart from that your question is not really clear because you say that if the user is not authorized you want to send him to the login page. Did you mean authenticated? That's 2 different things. If a user is authenticated (==logged in) but not authorized, what should he do on the login page? He's already logged in. - Michael Härtl
Oh sorry, I mean if user is not logged in he should be gone to login page. Your comment is good and it works, but tell me, how can I set controller/action for loginRequired() method? - user2218845
You can do it with accessRules just as PeterM explained. You don't need to add so many rules, though. Add one allow with 'users'=>'@' and one deny without any further parameters. Read all details here. - Michael Härtl
No, you didn't understand me. Now I invoke Yii::app()->user->loginRequired() and it moves me to "site/login" page. But I need to use another controller/action link. How can I fix it? - user2218845

4 Answers

1
votes

Use action filters, there is basic access control filter when you create yii crud. Here are docs about filters:
http://www.yiiframework.com/doc/guide/1.1/en/basics.controller#filter

Topics with ready solution for access controle is here: http://www.yiiframework.com/doc/guide/1.1/pl/topics.auth#sec-3

In short, create method in controller:

    public function filters()
    {
        return array(
            'accessControl',
        );
    }

And then define access rules for actions with method:

public function accessRules()
{
    return array(
        array('deny',
            'actions'=>array('create', 'edit'),
            'users'=>array('?'),
        ),
        array('allow',
            'actions'=>array('delete'),
            'roles'=>array('admin'),
        ),
        array('deny',
            'actions'=>array('delete'),
            'users'=>array('*'),
        ),
    );
}

EDIT

To define url for redirect if user is not authenticated, define it in user component:

'user' => [
                'class' => 'CWebUser', // or custom
                'allowAutoLogin' => true, // for autologin
                'loginUrl' => ['/ua/user/login'], // if not authenticated go here
     ]
0
votes

I have created AdminModule.php. In this, I have created a function that will check if the user is logged in or not. And also there are public pages, which doesn't require login.

public function beforeControllerAction($controller, $action)
{
    if(parent::beforeControllerAction($controller, $action))
    {   
        // this overwrites everything in the controller
        $controller->layout = 'admin';
        // this method is called before any module controller action is performed
        // you may place customized code here
        $route=$controller->id.'/'.$action->id;
        $publicPages=array(
            'user/login',
            'default/error',
        );
        if($this->password!==false && Yii::app()->user->isGuest && !in_array($route,$publicPages))
            Yii::app()->user->loginRequired();
        else
            return true;
    }
    else
        return false;
}
0
votes

As a simplified version of Mohit Bhansali's example, I implemented the following code in my AdminModule:

public function beforeControllerAction($controller, $action)
{
    if(parent::beforeControllerAction($controller, $action)) {
        if (Yii::app()->user->isGuest) {
            Yii::app()->user->loginRequired();
        } elseif (Yii::app()->user->id != 'myadminuser') {
            throw new CHttpException(403, 'You are not authorized to perform this action.');
        }

        return true;
    } else {
        return false;
    }
}

I was then also able to remove from each admin module controller the accessControl array return in filters() (must keep the empty filter() function in place, though), and completely remove accessRules(). For example, here is the DefaultController:

class DefaultController extends Controller
{
    public function filters()
    {
    }

    public function actionIndex()
    {
        $this->render('index');
    }
}

It's also worth mentioning that using RBAC would be advised for anything more than simple access control, and if we were using RBAC here, we'd call Yii::app()->user->checkAccess() instead of checking Yii::app()->user->id in AdminModule.

-1
votes

Just add this

if(Yii::app()->user->getId()===null) {

      // This is the case where user is not logged in so redirect
     $this->redirect(array('site/login'));

} else {

     // this is the case where user is logged in 
     // do your business 

}

There is a really good SO posting which is already existing , you can refer to that for your case

How to authenticate user on index page in Yii

Hope this helps