前言:
很久沒用yii2寫登陸了。有些細節都有些忘了,寫一篇加深下印象,本次做的使用者登陸,使用的是yii2 user元件中的login方法來儲存使用者登陸狀态,這也是yii2比較優秀的地方,很多地方不用我們操心
目錄:
- 使用資料遷移,完成建表
- 完成注冊
- 完成登陸
- yii2中自帶了一個user表的資料遷移
資料遷移
我們在控制台目錄下找到它的位置
然後用指令行來執行資料遷移
image.png
當資料表建好了之後,我們需要在表中添加一個字段
資料表
就是最後的salt(鹽值),字元形 32位,這個主要是用于密碼加密,是目前比較流行的也是安全性比較高的加密方式
注冊頁面我選擇使用ActiveForm來做一個表單,需要使用ActiveForm就必須在渲染視圖方法中給頁面傳遞一個模型對象來配合使用
/**
* 渲染注冊頁面
*/
public function actionRegist()
{
$userModle = new User();
return $this->render('regist', ['usermodel' => $userModle]);
}
由于隻是測試使用,并不是實際工作開發,這裡注冊就隻做了賬号密碼和郵箱,并且沒有涉及發郵件技術,如果對發郵件感興趣的朋友可以點選看我另一篇部落格
yii2發郵件。這裡就不多介紹了
頁面我選用了bootstrap架構來做一個簡單的表單
下面來看控制器部分
/**
* 完成注冊
*/
public function actionRegistTodo()
{
//通過自己封裝的私有方法來接收前台送出的表單資料
$formData = $this->_getRequest();
//建立模型對象
$userModel = new User();
//将資料綁定到模型對象中
if (!$userModel->load($formData)) {
exit('綁定資料錯誤');
}
try {
//調用模型中的建立使用者的方法
if ($userModel->createUser()) {
echo '注冊成功';
}
//捕獲建立新使用者方法中抛出的異常
} catch (Exception $exception) {
//列印異常的資訊
var_dump($exception->getMessage());
}
}
控制器部分方法比較簡潔,重點是控制器中調用的模型層的createUser方法
在建立使用者之前,我們需要對前台傳遞過來的資料進行驗證,我們知道程式員永遠不能相信使用者送出的資料,對于使用者的送出,驗證是必須的
由于我們的模型類繼承了ActiveRecord
class User extends \yii\db\ActiveRecord
是以我們可以使用父類中的validate方法來驗證表單資料
if (!$this->validate()) {
throw new Exception($this->getErrors());
}
當調用validate方法後,它會擷取到們之前寫好的rules方法裡面的驗證規則,如果資料符合驗證規則,傳回true,不符合傳回false,并且會将不比對的提示資訊綁定到模型對象上,我們可以通過getErrors方法來擷取
驗證方法
當驗證通過後,我們就可以對密碼進行加密了,我們使用加鹽加密。
- 首先我們需要生成随機的鹽值
$salt=Yii::$app->security->generateRandomString();
我們調用secrurity元件上的generateRandomString方法來生成一個32位的随機數
- 将使用者輸入的密碼和鹽值拼接,随後用security元件中的哈希方法進行加密
$this->password_hash=Yii::$app->security->generatePasswordHash($this->password_hash.$salt);
加密方式按個人喜好,也可使用md5加密
- 将生成的鹽值綁定到模型對象上
$this->salt=$salt;
鹽值需要儲存到資料庫中,用于使用者登陸時進行加密對比
- 儲存到資料庫中
if (!$this->save(false)) {
throw new Exception($this->getErrors());
}
由于其他資料在通過load方法綁定到模型上,我們将加密後的密碼和鹽值綁定上後,就可以儲存到資料庫中了
這裡有個小細節,當我們調用模型中的save方法儲存資料的時候,save方法還會調用validate來驗證資料,由于我的驗證規則中有驗證兩次輸入密碼必須一緻,當我們的密碼加密後,就和之前的重複密碼不一緻了,這樣就會導緻報錯。解決方法就是在save方法中傳入一個false,這樣就不會在save的同時進行驗證了
同樣的,登陸我們也是使用的ActiveForm和Bootstrap架構來寫表單,不同的是,我們登陸還加入了驗證碼 (驗證碼這次就不細談了)
- 前端頁面部分
<?php $form = \yii\bootstrap\ActiveForm::begin(['action' => \yii\helpers\Url::to(['login/login-check'])]) ?>
<table>
<tr>
<!-- 使用者名-->
<?= $form->field($model, 'username') ?>
</tr>
<tr>
<!-- 密碼-->
<?= $form->field($model, 'password_hash') ?>
</tr>
<tr>
<!-- 重複密碼-->
<?= $form->field($model, 'repassword') ?>
</tr>
<tr>
<!-- 驗證碼圖檔-->
<td><img style="cursor:pointer;" id="captchaImg" src="<?= \yii\helpers\Url::to(['login/captcha']) ?>" alt=""></td>
</tr>
<tr>
<td>
<label for="captcha">驗證碼</label>
<!-- 驗證碼輸入框-->
<input type="text" name="captcha" class="input-xxlarge">
</td>
</tr>
<tr>
<td><input type="submit" value="送出" class="btn btn-success"></td>
<td><a class="btn btn-warning" href="<?=\yii\helpers\Url::to(['login/regist'])?>">注冊</a></td>
</tr>
</table>
<?php $form::end(); ?>
前面已經介紹過頁面,登陸頁面和注冊頁面類似。
- 控制器部分
首先是判斷驗證碼是否正确
驗證碼
綁定資料,驗證資料
驗證資料
調用模型方法,查找使用者,如果賬号密碼比對,調用user元件中的login方法完成登陸
在綁定資料驗證資料的時候,有個小細節,這時我們的業務隻需要驗證使用者名和密碼,并不需要驗證郵箱,可我們的驗證規則中寫了郵箱。或則在以後我們驗證規則中别的什麼字段的時候,我們可以采取部分驗證
//驗證部分資料(隻驗證使用者名,密碼,重複密碼)
if (!$userModel->validate(['username','password_hash','repassword'])) {
die('資料非法');
}
将要驗證的字段以數組形式傳入validate就可以了,這樣就隻會驗證你傳入的字段的驗證規則.我稱之為部分驗證
- 模型部分
首先我們要使用yii2自帶的login方法來儲存登陸狀态,我們需要我們的user模型繼承IdentityInterface身份驗證接口,并且實作它裡面的抽象方法
繼承接口
下面是實作接口的代碼
/**
* 通過傳遞的id,傳回查到的資料模型對象的靜态方法
* @param int|string $id
* @return static
*/
public static function findIdentity($id)
{
return User::findOne($id);
}
/**
* 通過傳遞token,傳回查到的資料模型對象的靜态方法
* @param mixed $token
* @param null $type
* @return static
*/
public static function findIdentityByAccessToken($token, $type = null)
{
return User::findOne(['password_reset_token'=>$token]);
}
/**
* 傳回目前對象的id
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* 擷取目前對象的auth_key
* @return mixed
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
*對比傳遞過來的authkey于目前對象的auth_key
* @param string $authKey
* @return bool
* 傳回對比結果
*/
public function validateAuthKey($authKey)
{
return $authKey===$this->getAuthKey();
}
前面的準備工作,搞定過後,我們就可以來完成登陸驗證
我們登陸分三部
- 擷取使用者輸入的使用者名,判斷是否有這個使用者
- 将鹽值從資料庫中取出,并于使用者輸入的密碼拼接
- 将加密後的使用者輸入的密碼,和資料庫中存儲的密碼進行比對
任意一步失敗,則抛出異常
第一部
$username=$this->username;
$password_hash=$this->password_hash;
//查詢資料表中使用者名
$userModel=User::findOne(['username'=>$username]);
if (empty($userModel)) {
throw new Exception('使用者或密碼錯誤');
}
第二部
//賬号存在,對比密碼
$salt=$userModel->salt;
//使用者表單送出的密碼加密
$securityPassword=$password_hash.$salt;
拼接後的密碼不需要進行hash加密,我們使用yii2 security元件中的validatePassword的方法來比對
第三部
if (!Yii::$app->security->validatePassword($securityPassword,$userModel->password_hash)) {
throw new Exception('使用者或密碼錯誤');
}
return $userModel;
密碼驗證通過後,則傳回查找到的資料模型對象
控制器擷取到了資料模型對象後就可以調用user元件中的login方法,進行儲存使用者登陸的狀态了
好了,本次回顧yii2登陸注冊的介紹了就寫到這裡了,如果有什麼地方不對,希望大神指正.謝謝
以上