over 3 years ago

Yii 提供兩個 class 來實做登入機制

1.CUserIdentity
2.CWebUser

CUserIdentity->負責實做登入的操作細節
CWebUser(用 Yii::app()->user 呼叫)->負責記錄登入後的資訊


執行流程

1. View 的 login form
2. post 到 Controller
3. Controller new 一個 CUserIdentity,帳號密碼放入 CUserIdentity 的 instance 中
4. CUserIdentity 執行 authenticate method(需要覆寫),做細節處理,帳密比對之後,就傳true反之false
5. CUserIdentity 的 authenticate 成功之後 Controller 呼叫 CWebUser(Yii::app()->user) 執行 login method
6. CWebUser login method 會呼叫 CUserIdentity 的 getPersistentStates method,取得在 CUserIdentity 中 authenticate method 設定哪些 state e.g: $this->setState('email', $user->email);
7. CWebUser 把 state 資料放在 cookie 中
8. CUserIdentity 執行完操作細節,回傳 true/false ,表示登入成功或失敗
9. Controller 依照 UserIdentity 給的 authenticate 結果,做後續的操作


CWebUser 除了預設資訊外,可以額外自己定義資訊塞給 session

UserIdentity.php
$this->setState('email', $user->email);

然後可以這樣使用
Yii::app()->user->email

不過要注意的是,如果有塞秒數給 CWebUser 的 login(),就會把資訊也 copy 一份到 cookie 去,看這段,所以還要注意 config 的設定,簡而言之,機密資訊不能洩漏到 cookie 裡

portected/config/main.php
...
...
'components'=>array(
    'user'=>array(
        // enable cookie-based authentication
        'allowAutoLogin'=>false,   // <-- 記得改成false
    ),
...
...


可覆寫的 method

CUserIdentity

authenticate()->執行驗證操作

CWebUser

login($identity,$duration=0)->成功登入要執行的細節 e.g 設定 session、cookie 之類...


登入範例

protected/views/user/signinForm.php
<div class="form">
<?php echo CHtml::beginForm(Yii::app()->createUrl("user/signin")); ?>
 
    <div class="row">
        <?php echo CHtml::Label('username', ''); ?>
        <?php echo CHtml::TextField('username', ''); ?>
    </div>
    <div class="row">
        <?php echo CHtml::Label('password', ''); ?>
        <?php echo CHtml::TextField('password', ''); ?>
    </div>
    <div class="row submit">
        <?php echo CHtml::submitButton('Sign In'); ?>
    </div>
<?php echo CHtml::endForm(); ?>
 </div>
protected/controllers/UserController.php
<?php
    public function actionSignin()
    {
        if (!empty($_POST['username']) && !empty($_POST['password']))
        {
            $identity = new UserIdentity($_POST['username'], $_POST['password']);
            if ($identity->authenticate())
            {
                Yii::app()->user->login($identity, 3600*24*7);
                Yii::app()->user->setFlash('success', $this->setFlashMessage('Is Sign In NOW.'));
                $this->redirect(Yii::app()->createUrl('user/index'));
            }
            else 
            {
                Yii::app()->user->setFlash('error', $this->setFlashMessage("please Singn In. {$identity->errorMessage}"));
                Yii::app()->user->logout();
            }

        }
        
        $this->render('signinForm');
    }
protected/components/UserIdentity.php
<?php
class UserIdentity extends CUserIdentity
{
    private $_id;
    
    public function authenticate()
    {
        $user = User::model()->findByAttributes(array('username' => $this->username));
        if ($user === null)
            $this->errorCode = self::ERROR_USER_USERNAME_INVALID;
        else if ($user->password != $this->password)
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        else 
        {
            $this->_id = $user->id;
            $this->setState('email', $user->email);
            $this->errorCode = self::ERROR_NONE;
        }
        unset($user);
        return !$this->errorCode;
    }
}
protected/components/WebUser.php
<?php
class WebUser extends CWebUser
{
    private $_keyPrefix;
    private $_access=array();
}

2015/05/05 更正

UserIdentity,的職責,就是驗證通過之後給予一個識別,裡面有getId()這個method,
驗證過後,WebUser就要做login()的動作,把整個UserIdentity傳進去,
就會把UserIdentity$this->_id屬性傳給WebUser$this->id

TODO 未完待續...

← jquery pushstate Yii filter、beforeAction、beforeRender、afterAction、afterRender執行順序 →