Yiiframework 內建完整的用戶認證體系。本文層層剖析:自動生成代碼結構 → 核心類職責 → 數據庫驅動改造 → 自動登錄(Remember Me)原理與實現。
| 層級 | 文件/類 | 核心職責 |
|---|---|---|
| Component | UserIdentity | 最基礎的身份驗證邏輯(預設硬編碼 demo/admin) |
| Model | LoginForm (extends CFormModel) | 封裝表單數據、驗證規則、調用 UserIdentity、執行登錄 |
| Controller | SiteController::actionLogin() | 接收 POST、實例化 LoginForm、驗證並登錄或渲染視圖 |
| View | views/site/login.php | 登錄頁面模板 |
// LoginForm::authenticate() → UserIdentity::authenticate()
public function authenticate($attribute,$params) {
$this->_identity = new UserIdentity($this->username, $this->password);
if (!$this->_identity->authenticate())
$this->addError('password', '用戶名或密碼錯誤');
}
// LoginForm::login() → Yii::app()->user->login()
public function login() {
if ($this->_identity === null) { /* 實例化並驗證 */ }
if ($this->_identity->errorCode === UserIdentity::ERROR_NONE) {
$duration = $this->rememberMe ? 3600*24*30 : 0; // 30天 或 會話級
Yii::app()->user->login($this->_identity, $duration);
return true;
}
return false;
}
假設已建表 admin(字段:admin_id, username, psw[雙重 SHA1], nick, login_time)。
// components/UserIdentity.php
public function authenticate() {
// 1. 密碼雙重 SHA1(與存儲一致)
if (strlen($this->password) > 0)
$this->password = sha1(sha1($this->password));
// 2. 查找用戶
$user = Admin::model()->findByAttributes(['username' => $this->username]);
// 3. 驗證邏輯
if ($user === null)
$this->errorCode = self::ERROR_USERNAME_INVALID;
elseif (!($user instanceof Admin) || $user->psw !== $this->password)
$this->errorCode = self::ERROR_PASSWORD_INVALID;
else {
// 4. 設置狀態:登錄後可直接用 Yii::app()->user->nick 訪問
$this->setState('admin_id', $user->admin_id);
$this->setState('nick', $user->nick);
$this->setState('username', $user->username);
// 5. 更新最後登錄時間
$user->login_time = date('Y-m-d H:i:s');
$user->save();
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
// config/main.php
'components' => [
'user' => [
'class' => 'WebUser', // 或 CWebUser
'allowAutoLogin' => true, // 關鍵開關
'identityClass' => 'app\models\User', // Yii2 風格
],
],
protected function sendIdentityCookie($identity, $duration) {
$cookie = new Cookie($this->identityCookie);
$cookie->value = json_encode([
$identity->getId(), // 用戶 ID
$identity->getAuthKey(), // 驗證密鑰(防偽造)
$duration, // 有效期
]);
$cookie->expire = time() + $duration;
Yii::$app->getResponse()->getCookies()->add($cookie);
}
Cookie 內容:[user_id, auth_key, duration],經 JSON 編碼存儲。
getIdentity())。loginByCookie()。User::findIdentity($id) 獲取用戶對象。validateAuthKey($authKey) 防篡改。switchIdentity() 重建登錄態,並可選續期 Cookie(autoRenewCookie)。public function logout($destroySession = true) {
$identity = $this->getIdentity();
if ($identity !== null) {
$this->switchIdentity(null); // 關鍵:傳 null 觸發 Cookie 刪除
if ($destroySession) Yii::$app->getSession()->destroy();
}
return $this->getIsGuest();
}
自定義用戶模型必須實現:
findIdentity($id):根據 ID 找用戶findIdentityByAccessToken($token):API 認證用getId()、getAuthKey()、validateAuthKey($authKey)Yii 登錄體系設計精妙:UserIdentity 負責驗證邏輯,LoginForm 封裝表單交互,WebUser 管理會話狀態與 Cookie 持久化。遷移到數據庫只需重寫 UserIdentity::authenticate();自動登錄則靠 allowAutoLogin + Cookie(JSON) + IdentityInterface 三位一體實現。理解這套機制,靈活定製認證流程將得心應手。