Yii 1.1: Module based login

19 followers

If you want to add module based login to a site without using RBAC, please follow these guidelines.

Consider the situation where we want to add 3 types of login in a site: customer, dealer, and admin.

Start by generating three modules using gii. (To do this, please refer to this guide for module generation http://yiiframework.com/doc/guide/1.1/en/basics.module#creating-module)

Step 1

Copy the UserIdentity component to the module/components folder for each module. We will validate each module against its table. For example, customer validation is done using customer table, and admin validation against the admin table

For each module, change its UserIdentity authenticate() function to perform the appropriate validation.

Step 2

For each module, add the following lines to its main page. For example, for the Customer module, add to Customer/CustomerModule.php Add the following lines to init():

$this->setComponents(array(
            'errorHandler' => array(
                'errorAction' => 'customer/default/error'),
            'user' => array(
                'class' => 'CWebUser',             
                'loginUrl' => Yii::app()->createUrl('customer/default/login'),
            )
        ));
 
Yii::app()->user->setStateKeyPrefix('_customer');

Step 3

Create the login/logout action in each module's DefaultController.

For example, for the Customer module:

Create the actionLogin() in Customer/controllers/DefaultController.php.

Also, create actionLogout() as follows:

public function actionLogout() {
        Yii::app()->user->logout(false);
        $this->redirect(Yii::app()->getModule('customer')->user->loginUrl);
    }

Point sub-domain to module

This tips from the forum URL Subdomain to module

There is a feature called "Parameterizing Hostnames" (described on this pages). add the following lines to main.php

'components' => array(
   ...
   'urlManager' => array(
      'rules' => array(
         'http://customer.example.com' => 'customer/default/index',
         'http://customer.example.com/login' => 'customer/default/login',
      ),
   ),
   ...
),

So "customer/default/index" refers to the module "customer" with controller "default" and action "index".

Update

Redirect to respective module login, if user not logged in to a particular model

add following code to customer module CustomerModule.php in beforeControllerAction

if(Yii::app()->getModule('customer')->user->isGuest)
      Yii::app()->getModule('customer')->user->setReturnUrl('customer/default/login');

do the same for other module

in SiteController's site/login method

public function actionLogin() {
         Yii::app()->request->redirect(Yii::app()->createUrl(Yii::app()->user->returnUrl));
    }

(or)

Update 2 (best method)

Redirect to respective module login, if user not logged in to a particular model

add following code to customer module CustomerModule.php

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

do the same for other module

Thanks to ricardograna for sharing some configurations

Total 6 comments

#12253 report it
MaxPowers at 2013/03/09 05:23pm
Properly Setting Yii::app()->user->returnURL

I modified Update 2 to set the returnURL before redirecting to the login page, so once a user logs in they can be sent to the original page they requested. I have also implemented the generic naming suggested by other posts. Thanks to all who contributed - it got me started on this concept very quickly.

public function beforeControllerAction($controller, $action)
    {
        if(parent::beforeControllerAction($controller, $action))
        {
            // this method is called before any module controller action is performed
            // you may place customized code here
            $route = $controller->id . '/' . $action->id;
            $publicPages = array(
                'default/login',
                'default/error',
            );
            if (Yii::app()->user->isGuest && !in_array($route, $publicPages)){
                /*set the return URL*/
                $request=Yii::app()->request->getUrl();
                Yii::app()->user->returnURL=$request;
                /*redirect to module login form*/
                Yii::app()->getModule("{$this->id}")->user->loginRequired();
            }
            else
            return true;
        }
        else
            return false;
    }
#10855 report it
hemc at 2012/11/28 01:04am
problem when implement user level access

Please take a look to my problem. it working for me but create problem when implement user level access. http://www.yiiframework.com/forum/index.php/topic/37991-module-based-login-and-user-level-acces-system

#7727 report it
szaqal83 at 2012/04/12 04:02pm
Problem setting errorHandler

Hi, I can't get errorHandler working when it is being set this way:

$this->setComponents(array( 'errorHandler' => array( 'errorAction' => 'customer/default/error'), ...

it works when I set it by:

Yii::app()->errorHandler->errorAction='customer/default/error';

I would like to handle module errors "inside" my module rather than using main app errorHandler. Am I missing something important?

#6910 report it
Rituparna at 2012/02/12 03:36pm
Point sub-domain to module is not working

Point sub-domain to module is not working . I am using YII framework at one of my project and I am facing problem with Parameterizing Host Names, I have a module "ADMIN" and I want to display this as a subdomain within my domain, so I am setting rules like the following way from the protected/config/main.php: 'urlManager'=>array( 'urlFormat'=>'path', 'showScriptName'=>false, 'rules'=>array( '<controller:w+>/<id:d+>'=>'/view', '<controller:w+>/<action:w+>/<id:d+>'=>'/', '<controller:w+>/<action:w+>'=>'/', 'www.admin.moresoccerfun.com/login' => 'admin/default/index', ), ),

But when I am running the page: www.admin.moresoccerfun.com/login from the browser, it is showing "SERVER NOT FOUND". Please help me out from this problem. Thanks and looking for your response.

#4445 report it
jogle at 2011/07/10 01:21am
Thanks, thats all

If module has access rules is not required put redirect control on module, and it works ok only setting loginUrl and customize userIdentity in module.

#1982 report it
ricardograna at 2010/10/25 09:07am
Excellent

Particullary, I prefer to use module id, to make it more reusable

Yii::app()->user->setStateKeyPrefix("_{$this->id}"); Yii::app()->user->loginUrl = Yii::app()->createUrl("/{$this->id}/default/login");

And customize my UserIdentity (e.g. AdminIdentity, CustomeIdentity...etc) to avoid misunderstandings.

Leave a comment

Please to leave your comment.

Write new article