beforeLogin: not being called when the docs say it should be

The Definitive Guide recommends, in section 3 of the chapter entitled

"Authentication and Authorization", that one should override

CUserIdentity::authenticate and CWebUser::beforeLogin. I’ve been

trying to implement this, but I can’t get it to work. My problem is

that beforeLogin is not being called when I expect it to be.

To reproduce the behaviour that surprises me, do the following.

  • Install Yii 1.1.7.

  • Create a website using "yiic webapp SOME_DIRECTORY".

  • Access this website.

  • Log in, making sure to check "Remember me next time".

  • Edit CWebUser.php, changing beforeLogin so that it throws an exception.

(I know it’s normally not a good idea to change the Yii classes; I am

suggesting it here only to illustrate the problem I’m having.)

  • In the browser, follow the "About" link in the navbar of the new website.

I expect beforeLogin to be called at this point, and for the browser

to display an error message from Yii about an exception in beforeLogin,

but this doesn’t happen. Instead, I simply get the “About” page.

Therefore, I conclude that beforeLogin is not being called, which seems

to contradict the documentation.

By the way, I’m just starting on my first Yii site, so if I’ve got something wrong,

don’t be too hard on me.

Just in case the information is useful, I will list the software I used

for the above test:

  • Yii 1.1.7

  • PHP 5.3.3

  • Apache 2.2.16

  • Firefox 4.0.1

  • Debian Linux 6.0

The website and the browser were running on the same machine.

When do you expect it to be?

Before authentication? or before ‘login’ (http://www.yiiframework.com/doc/api/1.1/CWebUser#login-detail)

Remember that authentication happens before login the credentials




// default on LoginForm

public function login()

	{

		if($this->_identity===null)

		{

			$this->_identity=new UserIdentity($this->username,$this->password);

			$this->_identity->authenticate();

		}

		if($this->_identity->errorCode===UserIdentity::ERROR_NONE)

		{

			$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days

			Yii::app()->user->login($this->_identity,$duration);

			return true;

		}

		else

			return false;

	}



I expect beforeLogin to be called any time that Yii decides that a HTTP

request is from a logged-in user. (It might be called in other cases

as well, but those cases aren’t relevant to the present discussion.)

It may be worth pointing out that there’s a code path in which

beforeLogin is called without any call to CWebUser::login. This happens

if CWebUser::restoreCookie is called inside CWebUser::init.

And did you set the ‘allowAutoLogin’=>true, // enable cookie-based authentication ?

Yes. (It’s actually the default when you set

up a site with "yiic webapp".)

What about the ‘About’ page, how it is served? Is the SiteController serving the page? Is it static page? Have you set the access rules filter for that ‘about’ page?

I believe I’ve figured out the thinking behind Yii’s behaviour. When I

request the "About" page (as described in my original post), Yii finds a

session for me, so it has no need to read the user data from the cookie,

so it has no need to call beforeLogin.

Thanks for taking the time to help.