属个人理解,有出错的地方请评论指出,谢谢~
用户登录时,调用默认控制器siteController/actionLogin
public function actionLogin()
{
$model=new LoginForm;
{
$model=new LoginForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login())
$this->redirect(Yii::app()->user->returnUrl);
}
// display the login form
$this->render('login',array('model'=>$model));
}
用户提交表单后,实例化LoginForm模型,再实例化组件UserIdentity,调用UserIdentity/authenticate
public function authenticate()
{
$users=MngUserMain::model()->findByAttributes(array('username'=>$this->username));
if($users==NULL)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($users->password!==$this->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else{
$this->_id=$users->id;
$this->setState('department_id', $users->student_num);
$department = MngDepartment::model()->findByPk($users->student_num);
$this->setState('department_name', $department->name);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
{
$users=MngUserMain::model()->findByAttributes(array('username'=>$this->username));
if($users==NULL)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($users->password!==$this->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else{
$this->_id=$users->id;
$this->setState('department_id', $users->student_num);
$department = MngDepartment::model()->findByPk($users->student_num);
$this->setState('department_name', $department->name);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
通过数据库匹配用户输入,如果帐号密码正确,则让用户登录,LoginForm/login执行了这个操作
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;
}
{
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;
}
此处调用了Yii::app()->user->login($this->_identity,$duration)这个函数为CWebUser/login,用于生成session和为CWebUser实例的一些变量赋值
public function login($identity,$duration=0)
{
$id=$identity->getId(); //这里是记录的id
$states=$identity->getPersistentStates();// 这里是setState函数设置的一些额外的属性,是array
if($this->beforeLogin($id,$states,false))
{
$this->changeIdentity($id,$identity->getName(),$states) ;//$identity->getName()为返回CUserIdentity实例中的username的值
if($duration>0)
{
if($this->allowAutoLogin)
$this->saveToCookie($duration);
else
throw new CException(Yii::t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
array('{class}'=>get_class($this))));
}
$this->afterLogin(false);
}
return !$this->getIsGuest();
}
{
$id=$identity->getId(); //这里是记录的id
$states=$identity->getPersistentStates();// 这里是setState函数设置的一些额外的属性,是array
if($this->beforeLogin($id,$states,false))
{
$this->changeIdentity($id,$identity->getName(),$states) ;//$identity->getName()为返回CUserIdentity实例中的username的值
if($duration>0)
{
if($this->allowAutoLogin)
$this->saveToCookie($duration);
else
throw new CException(Yii::t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
array('{class}'=>get_class($this))));
}
$this->afterLogin(false);
}
return !$this->getIsGuest();
}
在changeIdentity中,设置了$_SESSION[$key]这个seesion,其实设置的是$_SESSION['前缀__id']=$id(记录的id),$_SESSION['前缀__name']=$username(记录的username),并且把我们自定义额外添加的一些属性也设置了$_SESSION['前缀+属性名']=$属性值(这里所指的额外属性是在UserIdentity组件中我们调用setState()函数设置的,以后可以通过Yii::app()->user->属性取值),如果$duration大于0(记住用户登录状态时间,默认是0),则设置cookie,allowAutoLogin是在main.php中设置的值(默认为true)。
protected function saveToCookie($duration)
{
$app=Yii::app();//实例化CApplication
$cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
$cookie->expire=time()+$duration;//cookie有效时间
$data=array(
$this->getId(),//用户的唯一标识符。如果是空,意味着用户是来宾用户。,返回的是$_SESSION[‘id’],
$this->getName(),//返回的是$_SESSION['username']
$duration,
$this->saveIdentityStates(),//返回一个名为$states数组,存储了我们自定义的额外属性
);
$cookie->value=$app->getSecurityManager()->hashData(serialize($data));//先返回CSecurityManager实例,再调用哈希函数hashData,返回的是加密过的数据
$app->getRequest()->getCookies()->add($cookie->name,$cookie);//添加cookie,cookie的name一般为$this->getStateKeyPrefix()
}
{
$app=Yii::app();//实例化CApplication
$cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
$cookie->expire=time()+$duration;//cookie有效时间
$data=array(
$this->getId(),//用户的唯一标识符。如果是空,意味着用户是来宾用户。,返回的是$_SESSION[‘id’],
$this->getName(),//返回的是$_SESSION['username']
$duration,
$this->saveIdentityStates(),//返回一个名为$states数组,存储了我们自定义的额外属性
);
$cookie->value=$app->getSecurityManager()->hashData(serialize($data));//先返回CSecurityManager实例,再调用哈希函数hashData,返回的是加密过的数据
$app->getRequest()->getCookies()->add($cookie->name,$cookie);//添加cookie,cookie的name一般为$this->getStateKeyPrefix()
}
$_SESSION[$key]中的$key=$this->getStateKeyPrefix().$key,其中getStateKeyPrefix()返回的是md5('Yii.'.get_class($this).'.'.Yii::app()->getId())
此后,当访问每一个控制器时,将通过调用Yii::app()->user->isGuest判断用户是否登录。
用户注销时调用CWebUser/logout销毁session,对于cookie,要看用户是否设置了记住登录,对于注销时cookie的消除并不太懂!以后再分析。
下面是logout动作,有些地方不清楚,请知道的人指点下~
public function logout($destroySession=true)
{
if($this->beforeLogout())
{
if($this->allowAutoLogin)
{
Yii::app()->getRequest()->getCookies()->remove($this->getStateKeyPrefix());//销毁$_COOKIE['$this->getStateKeyPrefix()']
if($this->identityCookie!==null)//identityCookie这个属性找不到在哪有赋值过!这里不清楚!我以为是用户选择了记住登录状态后,在用户注销时保存一些下次能直接登录用的cookie,
{
$cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
$cookie->value=null;
$cookie->expire=0;//但这里,当设置cookie过期时间为0或者忽略不设置的情况下,cookie将会在session过期后过期(即浏览器关闭后cookie过期)
Yii::app()->getRequest()->getCookies()->add($cookie->name,$cookie);
}
}
if($destroySession)
Yii::app()->getSession()->destroy();
else
$this->clearStates();
$this->afterLogout();
}
}
{
if($this->beforeLogout())
{
if($this->allowAutoLogin)
{
Yii::app()->getRequest()->getCookies()->remove($this->getStateKeyPrefix());//销毁$_COOKIE['$this->getStateKeyPrefix()']
if($this->identityCookie!==null)//identityCookie这个属性找不到在哪有赋值过!这里不清楚!我以为是用户选择了记住登录状态后,在用户注销时保存一些下次能直接登录用的cookie,
{
$cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
$cookie->value=null;
$cookie->expire=0;//但这里,当设置cookie过期时间为0或者忽略不设置的情况下,cookie将会在session过期后过期(即浏览器关闭后cookie过期)
Yii::app()->getRequest()->getCookies()->add($cookie->name,$cookie);
}
}
if($destroySession)
Yii::app()->getSession()->destroy();
else
$this->clearStates();
$this->afterLogout();
}
}