I have a really odd problem showing up the beginnings of my authentication for a small Yii app I am building. I have an "account" table set up in my database that is set up with a different primary key than an AUTO_INCREMENT id.
At this point, I am simply using the tutorial-level UserIdentity file supplied from here: http://www.yiiframework.com/doc/guide/1.1/en/topics.auth
I'm grabbing the login data from my form using POST and checking it in the controller as necessary.
public function actionLogin()
{
if( isset($_POST["username"]) && isset($_POST["password"]) ){
$identity = new UserIdentity($_POST["username"], $_POST["password"]);
if($identity->authenticate()){
$success = Yii::app()->user->login($identity);
$this->redirect(array('site/index'));
} else {
echo print_r($identity->errorMessage);
}
}
$this->render('login');
}
authenticate() returns true when entering proper credentials, and false when I put nonsense in the fields, as it should. After the authentication, it redirects to the index/home page.
Now, this is the part that doesn't make sense: In the index page, I am checking the state of my user by dumping the getId() method (which I have overridden), as well as checking a state variable I have set. In addition, when I
echo Yii::app()->user->isGuest;
to the screen, it returns false. Wow, great -- the login should be successful. WRONG.
When I do a dump of the user property of the app,
print_r(Yii::app()->user);
It shows the CWebUser being empty and as a guest. It's driving me insane.
CWebUser Object (
[allowAutoLogin] => 1
[guestName] => Guest
[loginUrl] => Array (
[0] => /site/login )
[identityCookie] =>
[authTimeout] =>
[autoRenewCookie] =>
[autoUpdateFlash] => 1
[loginRequiredAjaxResponse] =>
[_keyPrefix:CWebUser:private] => ccd216fa11757a8e75e940c97a24ee44
[_access:CWebUser:private] => Array ( )
[behaviors] => Array ( )
[_initialized:CApplicationComponent:private] => 1
[_e:CComponent:private] =>
[_m:CComponent:private] => )
Any insight? Is there an issue with my configuration or something I may have missed?
EDIT: UserIdentity Class
class UserIdentity extends CUserIdentity
{ private $_id;
public function authenticate(){
$record = Account::model()->findByAttributes(array('username'=>$this->username));
if($record === NULL){
$this->errorCode = self::ERROR_USERNAME_INVALID;
} else if($record->password !== crypt($this->password, $record->password)){
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->_id = $record->id;
$this->setState('username', $this->username);
$this->setState('friend_code', $record->friend_code);
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId(){
return $this->_id;
}
EDIT: I've checked some other things over, and updated my UserIdentity Class. I can now also get $_id from Yii::app()->user->id OR Yii::app()->getId().
I've found that Yii::app()->user->identityCookie doesn't exist, and I don't see any cookies other than PHPSESHID in my browser resources. Is this normal?
EDIT EDIT: So after seeing the first answer, I decided to take a look deeper into the CWebUser class. It looks like the only piece of the puzzle that may not be working is this line here.
$this->changeIdentity($id,$identity->getName(),$states);
// what this method actually looks like:
protected function changeIdentity($id,$name,$states)
{
Yii::app()->getSession()->regenerateID(true);
$this->setId($id);
$this->setName($name);
$this->loadIdentityStates($states);
}
I think I found the problem. Look at the following code from CWebUser:
public function getIsGuest()
{
return $this->getState('__id')===null;
}
It retrieves the $id
-attribute from your UserIdentity and bypasses the getId()
-method.
So to fix this, you should either scrap using your $_friend_code
-attribute and only use $this->id
, or add the following line in your authenticate()
-method in the second else-block.
// some code before this
else {
$this->_friend_code = $record->friend_code;
$this->id = $record->friend_code;
$this->setState('username', $this->username);
$this->setState('test', "test");
$this->errorCode = self::ERROR_NONE;
}
I recommend the first choice, as it tends to be the normal way to do things. But it's up for you to decide.
Hope this helped!
EDIT: another option would be to override the getIsGuest()
-method in CWebUser of course.